My Solution for Design an Efficient Parking Lot System with Score: 8/10
by dynamo_nectar738
System requirements
Functional:
- User should be able to make reservation to book the park lot if available
- User could get the park lot location and available in real time
- Each park lot has a detail information like space (large or small) for different cars. or if this park is for disabled individuals
- We should also highlight if this park has charge stations.
- We should allow user to book a park lot in advance.
- We should integrate with payment system to pay the parking fee
- User could cancel their parking if they could not arrive in time.
- We will keep the parking lot 15 minutes after the reservation time and cancel it automatically.
- User would get their notification if their reservation is success.
List functional requirements for the system (Ask the chat bot for hints if stuck.)...
Non-Functional:
List non-functional requirements for the system...
- System should be high availability
- System should handle the case of concurrent like different user book the same park lot in same time
- We should consider future growth of users and scalability
- We should keep our data security
- We should keep a low latency for book reservation and get the response of availability
- Let's assume the daily active user is 100000
- We assume only 80% of them will try to book a park, and all of them will get the park information at least 5 times.
- So the estimation write traffic would be 100000*0.8=80000 per day = 50 per minutes. and read traffic would be 100000*5 per day = 350 per minute = 6 per second
- Consider future growth, let's double the traffic, the write traffic would be 100 per minute = 2 per second. the read traffic would be 6*2=12 per second
- Consider there may be traffic spike in holiday, let's double again , so the peak write traffic in future would be 4 per second and read traffic would be 20 per second
- Let's go to the storage capacity, assume each reservation record cost 1KB, we take 4 record request per second , so daily record would be 24*4*3600*1KB=345MB, if we keep one replica, it should be 700MB, so yearly storage would be 700*365 = 255GB. we keep 4 year data retention for analysis, we need 1TB storage.
API design
- book a reservation
- POST /reservation/{user_id}/{park_lot_id}?start_time=${start}&end_time=${end}&type={type}
- cancel a reservation
- DELETE /reservation/{reservation_id}/
- Check available lots
- GET /reservation/{park_lot_id}/availability?start_time=${start}&end_time=${end}&type={type}
- Pay the parking fee
- POST /payment/{reservation_id}
- Get real-time available of parking lot
- GET /reservation/{park_lot_id}/start_time=${start}&end_time=${end}&type={type}
- Get detail information of a paring lot
- GET /park/{park_lot_id}
- Manage user's reservation
- GET /user/{user_id}?type=${type}
Database design
- User
- user_id PK
- user_name
- create_time
- Vehicle
- vehicle_id PK
- user_id FK
- vehicle_type enum
- Park_lot
- park_lot_id PK
- total_capacity
- small_size_park_capacity
- median_size_park_capacity
- large_size_park_capacity
- charge_station_park_capacity
- longitude
- latitude
- address
- status
- Reservation
- reservation_id PK
- user_id
- vehicle_id
- start_time
- end_time
- need_charge boolean
- reservation_status
- pay_status
High-level design
- App server
- user's side app to access our system
- server sider administration system to manage the park data
- API Gateway
- route traffic to different service and
- rate limitation
- audit log
- Reservation service
- To handle the request of add update or cancel the reservation
- Park-lot service
- To handle the add update request for park lot
- Return the real-time available information of park-lot
- To check if park lot have available lot for user
- Payment Service
- implement payment of user
- Notification Service
- push notification to user if his reservation finished
- Auth service
- authenticate user request to keep data security
- Feedback service
- collect user's feedback
- Loadbalance
- keep traffic balance in different server
- Cache
- cache data so give faster user experience
- DataBase
- store our data
Request flows
Reservation
- user request hit api-gateway and loadbalance, redirect to reservation service.
- reservation service will call park-lot service to check if available lot in this park-lot.
- if so, reservation service will create a record and save into db
- Then it will trigger a async task to notify user that his reservation is done
- If the reservation is not available, it will return a message to user to indicate have a retry
- If user cancel the reservation, it will update the status of record in database
- when user cancel the reservation advance, it will not charge fee, but if user does arrive in time and does not cancel the reservation, will call payment service to send a fee charge to user/
Payment
- When user's car arrive the park-lot, parking service will record this action and update the status of reservation
- when user leave, park-service will calculate the fee based on time and call payment service
- payment service will start a transaction ask user to pay
Detailed component design
Reservation Service
- our algorithm will allocate any lot exactly match user's requirement first, if it's available, we will create a reservation record.
- if there are no lot in match user's requirement but still other available lot, we will give a suggestion item to customer and give the decision to customer
- Conflict reservation: we will implement a optimistic lock mechanism to handler this case eg, if two user made reservation to same lot, then only one of them would successfully booked.
Cache
- To keep data consistent, after we update the record in database, then we update the corresponding item in cache
- For any GET request, it will hit cache and if no data existed in cache, then it would hit database.
- Each item in cache would have a expired time, and expired item would be evicted from Cache.
- We consider using redis as our cache layer
- When we update reservation record in DB, we will trigger a task immediately to update or add corresponding records in Cache to keep data consistent
Trade offs/Tech choices
Database
- The biggest trade off here is using RDBS instead of NoSQL, because:
- our payment service and book service has high requirement of transaction, eg ACID. this is a big pros of RDBS
- our data capacity is not extremely huge so RDBS is okay to handle this
- RDBS:
- pros: ACID transaction guaranteed, strong consistency view of data
- cons: we need to design our data schema carefully
- NoSQL:
- pros: data schema is flexible to change. more easy of horizontal flex up
- cons: eventually consistency instead of strong consistency, NO ACID transaction
Failure scenarios/bottlenecks
Failure scenarios
- Concurrent reservation request
- Scenario that different user make a reservation to same park-lot and there is only one available park.
- one user would get the failure return information and he need to retry to make another request
- Notification service failed
- As our notification is an async task to give more faster user experience, but it may failed,
bottlenecks
- In peak time, there may a large amount of user to book reservation , so the database performance would be a bottleneck
- We could shard the database based on different country or location
- We introduce a cache so the read traffic would hit cache first and it will return directly if cache hit
Future improvements
- Notification service failed
- We could have retry mechanism or has a message queue