I created a mobile game backend that contains progress and tournament logic. Tournament has matchmaking system that is required to run in real-time. I wanted to backend to be scalable and efficient as much as possible in order to handle large load.
In order to satisfy the real-time requirements of the game, I decided to utilize redis to achieve real-time constraints. I used Redis for caching and accessing sorted data quickly. Besides using Redis I also went with pure JDBC in order to eliminate abstraction overhead and have more granular control over database interactions. The same principle also applied to interactions with Redis. I directly interacted with Redis using quite a low-level API. That way I aimed to reduce overhead and unexpected performance bottlenecks due to unpredictable underlying abstractions.
Other than these decisions I made use of batching and concurrency where it is possible and needed.
For me the most challenging part was the group matching part because of the requirements, I needed to match at the moment of request made and return a leaderboard back. This limited me quite much because I couldn't make any use of async processing or decoupled architectures. Instead, I tried to rely on database transactions but in such a high-load system it suffered deadlocks inevitably. Even though I implemented deadlock recovery mechanisms it was not enough. So instead I switch synchronization at the application level. I used monitors to synchronize the access to the shared resources. I agree that this decision is not even close to the optimal solution but for the correctness of the program I stick to it. I have better solutions for a little relaxed version of the requirements that I would love to discuss.
I wrote many unit tests aiming at the service layers. Unfortunately, I didn't have time to increase test coverage any further, so I prioritized the service layer. In addition to unit tests, I tested the system for multiple cases using JMeter and made use of it while testing concurrent scenarios.
I dockerized the redis as well so all components can be run using docker-compose.
docker-compose up
I shared an exported Postman Collection in the root directory of the project. You can
import it and test the endpoints.
Additionally, I also shared a file called Dream.http
that you can use to test the endpoints using IntelliJ IDE.