Context: A limited resource (such as an item stock in an e-commerce) with a high burst of requests to read and write to it concurrently.
https://chatgpt.com/share/6783cf2b-0068-800e-bfc0-19dfd5158021
Lock the row that contains each item’s available stock on each read or write to ensure consistency of the data.
Extremely costly, as every request hangs until the lock is released and they are able to access it.
With each operation, 2 key pieces of data must be provided: original data read, and data that they wish to write.
When a transaction is processed, the data originally read is checked against the current value. If it’s different, you can either reject the transaction (in which case it may be automatically retried) or you can see what the delta trying to be written is, and if it can be honoured (say they purchased 2 items and 34 are left, then it doesn’t matter that the original amount that was read was 43, there are enough left that 2 can be sold).
Using a service such as Redis/Valkey you can allocate as many tokens as units you have of an item, and every time the item is added to the cart you can ask for one such token. This could even be distributed (each instance gets X amount of tokens). Each one would have a TTL so they can’t be held indefinitely, and if the user takes too long to finish the purchase, they’ll have to ask for another token later on, at which time there may not be any left. Otherwise their operation goes through and the token is consumed.
Whatever system you use needs to know how to replenish/release the token if it’s not consumed after TTL.
If having to refund people is not an issue, you could just do eventual consistency and let everyone’s purchases go through as individual operations. Later on, when merging them, refund or compensate users whose transactions were not actually fulfilled. Available stock is updated as transactions are processed, such that at some point no more purchases are accepted, but many may have happened that can’t later be honoured.
It’s costly from an operations standpoint, but much easier to implement on the technical side.