The simple top-10 leaderboard of the past is no longer a thing. Video game leaderboards have become a technical challenge on themselves if we take into account the sheer amount of data we have to handle to create them.
Popular video games might have to deal with millions of concurrent players constantly scoring new points. Even non-game-related industries are adopting gamification to increase user interest in their product. This translates into using different data points to generate a leaderboard of the same complexity as video game companies.
The challenge, in this case, revolves around providing exact, reliable yet fast access to a very narrow set of data points to design a leaderboard system that is both useful and usable. In other words, a real-time gaming leaderboard that anyone can query.
The data shown on the leaderboard needs to be exact by the sheer nature of it. Nobody is interested in seeing how many points they probably have. Instead, they want to know exactly how many points they're winning by, or losing by, to their friends.
This point is two-fold. On one hand the data needs to be reliable in the sense that the numbers can't lie. If you can't trust in the analytics then you don't trust the product that provides them. The other side of this point is that the data needs to be accessible at all times. Reliable access generates trust and keeps the user experience from going down the hill. This is especially true when millions of users are constantly checking it for updates. The data needs to always be there and updated as soon as possible.
This takes us to our last, yet very important, point: accessing this data has to feel fast. After all, in the eyes of our players (or users), we're listing a Top-XX list of values. We're not dealing with a lot of data, why wouldn't this be fast? And while that question might be an oversimplification, the product needs to ensure the experience. You can't let the leaderboard become the bottleneck of the user experience.
Build a leaderboard using Redis™*
We can solve all these challenges with a single product: Redis on Linux, and Memurai on Windows. Redis and Memurai act as an in-memory cache, making data reads and writes already very fast (faster than any human can perceive, in fact). Not only that, but there is one data type that can very well solve all our computational problems: Redis Sorted Sets.
One of the technical challenges of a real-time gaming leaderboard, is to keep that information updated and sorted at the same time, so that we can quickly display it whenever we need it. Sorted sets allow us to insert data into a container, keep it sorted automatically and as an added bonus, we're ensured that there are no duplicated records. Thus simplifying our writing logic.
Other operations on top of this data type allow you to:
* Increase and decrease their scores by arbitrary amounts with an
O(log(N)) complexity. In practical terms this means it takes less time than required to go through all elements inside the leaderboard.
* Query a random range within the leaderboard and return their scores.
* Getting the greatest score in the leaderboard in a single command.
* Even intersect two leaderboards to capture the top winner, or aggregate points for the same users. This can be useful if you're dealing with more than one list of top users.
Creating a leaderboard of 5 elements and querying the top 3 scores is as simple as:
> zadd leaderboard 200 John 123 Mark 500 Steve 98 Jeff 999 Elon > zrevrangebyscore leaderboard +inf -inf LIMIT 0 3 Resulting in: 1) "Elon" 2) "Steve" 3) "John"
Note that using the
zrevrangebyscore command is needed because by default sorted sets will return elements ordered by scores from low to high.
And given a second leaderboard for a different game, you can compute the overall common players by creating a new Sorted Set like this:
> zadd game2leaderboard 99 John 67 Mark 400 Steve 9 Elon > zinterstore commonleaderboard 2 leaderboard game2leaderboard > zrevrangebyscore commonleaderboard +inf -inf LIMIT 0 3 Resulting in: 1) "Elon" 2) "Steve" 3) "John"
These are all potential use cases that are resolved natively by Redis without forcing you to code any extra logic.
A reliable and reactive architecture
Not only does Redis solves all your data problems with a simple install but it also provides you with a very dynamic architectural tool.
Both in its High Availability configuration (using Sentinel) as well as in Cluster mode, Redis provides very scalable and resilient storage that can handle any amount of workload. And if on top of that, you make use of key-space notifications, you'll have the ability to react to changes in your leaderboard the moment they happen instead of having to write logic to check for them yourself.
* Notifying a user when they reach the top.
* Letting others know when they're no longer winning.
* Sending updates when points change.
* Performing secondary tasks when a user reaches a threshold.
These are all activities that can enrich your leaderboard but that require you to be aware of the leaderboard at all times. Through Redis' keyspace-notifications you're able to react to changes in the data by getting notified by Redis itself when something happens (writes, deletes, expirations, updates and so on). That way you're able to write microservices dedicated to different tasks without affecting your overall logic. Thus providing you also with a simple scaling model for your logic. Every time you require a new action, just add a new microservice, no need to modify existing logic or create a bloated and coupled project.
Solving all these problems with a Windows-native solution
While Redis is the perfect solution for a quick and reliable leaderboard data storage, making it work properly on Windows can be challenging. This is why Memurai, being a Redis-compatible Windows-native solution can be the perfect choice. It's just as reliable and performant (in some cases even faster) than the original.
With Memurai you're ready to build your solution and since it's fully compatible with the Redis API, any library on any programming language that already supports it will be perfect for the task.
* Redis is a trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Memurai is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and Memurai