How BookMyShow auto-deallocate seats for incomplete transactions(System Design)
There has been a serious interest in terms of how movie ticketing system like BookMyShow maintains auto-deallocation of seats after 15 minutes for incomplete transaction like payment not completed.
- When two seats are selected and clicked Pay by a Guest user and then do nothing.
2. When another use visits the same show and sees the those two seats are not available for booking.
Thus, BMS manages to hold those two seats for a specific duration of time and de-allocate automatically after certain threshold, 15 minutes(say).
How to implement ?
As you would be already having a table storing some mapping between the show and the seats and maintain another table for active reservations for any booking that has been requested whether complete or incomplete.
Whenever a booking request comes, follow the sequence.
- Whenever a new request comes, and payment button is clicked, insert into Reservation table and also updates the ShowSeatMapper table with the allocated seats so if a new user comes and again fetches the list of seats for a particular show, it would see them as allocated already.
- For concurrency control, we can utilize database serializable transaction isolation as from the middleware it is not possible to maintain states or sync between multiple JVMs deployed over multiple instances and hence will not be able to implement consistent concurrency.
- If the payment is successful, remove the row from the Reservation table and insert into Booking table, which will be responsible for all the successful and completed bookings.
- Using a job scheduler to go through the records in the Reservation table periodically and check if a particular record has been more than threshold and also payment is not complete. If this condition holds true, then remove the row and also update the ShowSeatMapper table with the updated list of allocated seats and this would eventually release the seats.
There is an alternate theory/design in terms of choosing a distributed cache which has inherent property of TTL and events would expire automatically triggering a callback of updating the DB. If we take example of Redis which supports https://redis.io/topics/notification but there is one caveat. Basically
expiredevents are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero
3. Thinking in terms of performance overhead, we can try to keep the Reservation table as small as possible. With reference to (4) above, if the job sees the payment is successful, and whether threshold has expired or not, it would remove the row and move to the Booking table.
4. All the notifications and post processing would be consumed from the Booking table.