users are able to check remaining spots in real time;
remaining spots are updated when vehicles enter & exit the parking lot
100 ~ 200 peak read qps
reliable, scalable
read consistency doesn't have to be strong (users can get slight outdated data)
100 ~ 200 peak read qps
support ~ 500 vehicles maximal
~50 parking lots
takes about 1 min for a vehicle to enter or leave a parking lot, so write qps is at most 50 * 2 (because enter + exit) / 60 = 1.67, which is relatively low
REST APIs for write (enter & leave parking lot)
/v1/enter
request: {
Enum vehicleType (can be car, motorbike, van),
Int parkingLotId
}
response {
boolean successful
}
/v1/exit
request: {
VType vehicleType (can be car, motorbike, van),
Int parkingLotId
}
response {
boolean successful
}
Read API
checkAvailableSpots
request {
list
}
response {
Map
}
since the data size is relatively small and write qps is limited, we can use a relational db to hold the data
int parkingLotId
int remainingCarSpot
int remainingMotorBikeSpot
int remainingVanSpot
int address
int lat
int lng
int geohash
the data can be indexed on id and geocode. Geohash are derived by lat and lng. It can help support features like searching the nearby parking lots given users current location
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
Database:
the data size is small (we don't need partition), all the requests come from the same region (no need for multi data center).
That being said, we can add replicas to provide reliability and prevent data loss, as well as scaling the system to support 100 ~ 200 peak read qps
For write operations, we can utilize relational db's own ACID and guarantee data consistency during concurrent write. And due to the nature of parking lot, it's unlikely we will see concurrent write of the same parking lot id
For read operations, since we can compromise consistency a little bit, we can directly serve the request without holding a lock, and directly read from replicas. We can also use Redis to hold the cache data to serve read faster and a higher qps
Notification System:
we can use a websocket protocol for the communication between user and server. Clients side can cache the remaining spots results, and notification system can push events include info like lot id, vehicle type and event type (enter, exit) to clients. Clients can then apply the changes to its cached data. Clients can periodically querying the parking lot management system to update the remaining spots results (cache). Since read consistency can be compromised, we don't need to do a lot of extra upgrade for events like notification missing/failed to deliver to clients
compromise read consistency to support a higher read qps
Users try to enter a parking lot with no remaining spot:
When user tries to enter the parking lot, the system will call the write API. The write API will hold a lock of the lot id's db record, check whether there's remaining spot. If yes, data will be modified and a successful response will be returned. If not, unsuccessful response will be returned, and ticket won't be issued.
It's unlikely to have 2 cars entering the parking lot concurrently, but even if we have this corner case, we can eliminate this by holding a lock on the parking lot id in the write path.
backend services can be scaled separately to accommodate increasing traffic.
DB sharding may be introduced if we have much more parking lot
The app may be able to display the nearby parking lots based on user's location. So geo data needs to be added to the db for each lot