A simple .NET demo project to illustrate how to prevent race conditions in a distributed environment using RedLock.net and Redis.
The purpose of this project is not to build a full-featured reservation system, but to provide a clear and simple example of solving a common concurrency problem: race conditions.
It demonstrates how to implement a distributed lock to ensure that a critical resource (like a cinema seat) can only be processed by one request at a time, even when multiple servers or instances are running.
Imagine a popular movie has only one seat left. Two different users click the "Book Now" button at the exact same moment.
- Request A reads the database and sees "1 seat available".
- Request B reads the database at the same time and also sees "1 seat available".
- Request A processes the booking and updates the seat count to 0.
- Request B, unaware of Request A's action, also processes the booking and updates the seat count to 0.
Result: The same seat is sold twice, leading to data inconsistency and an unhappy customer.
This project uses RedLock.net, a C# implementation of the RedLock algorithm, to solve this problem.
Before attempting to book a seat, the application tries to acquire a lock on that specific seat's ID.
- A request comes in to book
Seat-7. - The system asks Redis (via RedLock) to create a lock for the resource key
"seat-7". - If the lock is acquired successfully: The application proceeds with the booking logic. No other request can get a lock for
"seat-7"until this one is finished and releases the lock. - If another request for
Seat-7arrives: It will fail to acquire the lock and will be informed that the resource is currently busy (locked), preventing the double-booking.
This ensures that the process of "checking availability and booking" is atomic across a distributed system.
- C# & ASP.NET Core: For building the web API.
- Redis: As the distributed cache and lock manager.
- RedLock.net: The client library used to implement the distributed lock algorithm.
- .NET SDK (6.0 or later)
- Docker (or a running Redis instance)
-
Start a Redis instance: The easiest way is using Docker:
docker run --name my-redis -p 6379:6379 -d redis
-
Clone the repository:
git clone https://github.com/alireza-haeri/Reservation.git cd Reservation -
Configure the application: Ensure the
appsettings.jsonfile points to your Redis instance (the defaultlocalhost:6379should work with the Docker command above). -
Run the project:
dotnet run
To see the lock in action, use an API client like Postman or curl to send multiple, near-simultaneous requests to the booking endpoint.
- Endpoint:
POST /api/reservation - Body:
{ "seatId": "A1" }
Send 5-10 requests for the same seatId at once. You will observe that only one request succeeds (e.g., returns 200 OK), while the others will fail (e.g., return 409 Conflict or a similar status), proving that the distributed lock correctly prevented the race condition.
- Email: [email protected]
- Telegram: @AlirezaHaeriDev
- LinkedIn: in/alireza-haeri-dev