Max capacity is 100,000.
Let's say that in peak hour we get around 80,000 cars.
10% of lots would be for trucks
25% - for motorcycles
65% - for cars.
Number of exits should be proportional to the number of available parking lots.
If we have 80000 cars in one hour.
One car takes 20 seconds to enter.
80000/60 = 1333 cars arrive per minute
1333 / 3 = 440 cars arrive per 20 seconds
So we need approximately 440 entrances.
For simplicity let's say that for exit we need the same time, so we need 440 exits as well.
POST
parkCar(type) - when the car tries to enter, system tries to park in the system, it gets the type of the car, looks at available slots, if it doesn't have any, returns an error response. Otherwise, returns the ticket.
POST
pay(ticketId, paymentType) - paying the ticket when exiting the parking. Returns receipt.
Database will be RDB, because we have structural data like parking type, ticket, car, receipt.
The car gets to the entrance, tries to get the ticket by providing the car type, the request goes to the application server, which gets the parking availability from the cache, in case there is no entry, gets the data from the DB and updates the cache afterwards.
The same flow is for checking out at the exit, but without using the cache, and checking the parking availability.
The space in the DB can be divided into car type + number of available slots.
LRU cache eviction policy works well here. But our cache won't be overflowed ever, because we don't need much data in there.
Cache can actually be stored in the application as a structure, because we don't store a lot of data in there.
We can replicate an application server to avoid SPOF. We don't need checkpointing because our server is stateless.
Application server will use the Queue structure to handle the cars that were denied due to space limit. It will use First In First Out.
There is no much need of sharding the DB, due to low amount of data. But sync replication to a couple of nodes will work well to avoid SPOF.
In case the ticket was lost, we will have an entry with the car plate in the system, time of arrival, bill, name of the driver etc.
We could be using a dedicated cache as a separate server, which would provide us decoupling, but it is not worth the effort and cost, as it can the data is small in case of the parking system, and we can easily reload it from the RDB.
Alternative to sync replication in the DB, would be async, which would speed up write requests, but in the parking system we highly value consistency over a little write latency.
In case all our application servers fail, we would lose the cache, as it is co-located with the application servers, but it would be pretty easy to restore it from the DB.
If we get to many cars at once at multiple entries, we will face latency in our system, due to sync replication.
Separate entrance from exit servers to separate the load.