“Do you want to implement a real-time leaderboard for your next online game with Redis? Redis provides an out-of-the-box solution for this with ZSETs, which is a short name for Redis Sorted sets and is a tool that every Redis user must be familiar with.
Redis ZSET is an ordered collection of unique members where each member is associated with a score value. To highlight, the ZSETs are ordered by their score value by default which makes them quite different from the regular SET type. In addition, more than one member can hold the same score value, and the members will be ordered lexicographically in that case. The Redis ZSETs are a better choice for priority queues, secondary indexing, low-latency leaderboards, and rate limiters. Because ZSETs provide real-time demands such as responsiveness and in-memory access with low latency.
Furthermore, each member is assigned a rank value based on their position in the ZSET that is more like a 0-based index in a Java array.”
A Quick Look at Basic ZSET Commands
Several basic commands are available to add, fetch, and remove members from a ZSET(Sorted set) stored at a given ZSET key. Let’s have a quick look at three main commands: ZADD, ZRANGE, ZRANK, and ZREM.
A Real-time Pokemon Game Leaderboard example will be demonstrated here.
Upon user registration, we need to add each user to our ZSET named Pokemon:Leaderboard. So, the ZADD command is the ideal candidate to use as follows. Assume we got five players registered initially. So, the scores will be assigned to 0.
The return value is 1, which means one member has been added to the ZSET stored at key Pokemon:Leaderboard. If the member is already available in the given ZSET, only the score value will be updated.
We are all good to proceed. So, let’s go ahead and add the remaining four players to the ZSET: Pokemon:Leaderboard.
ZADD Pokemon:Leaderboard 0 zakariah
ZADD Pokemon:Leaderboard 0 bob
ZADD Pokemon:Leaderboard 0 mary
All five members have been added successfully. Next, we should examine or query the added members using the ZRANGE command. The ZRANGE command allows retrieving members that are sorted in a given range. A range can be specified by rank, score, or lexicographical values.
Let’s query all the members by specifying the range by rank values.
As expected, all five members have been returned and ordered lexicographically because the score values are the same for all members at this point. In addition, 0 is the starting index/rank of the range, and -1 denotes the top index of the given ZSET.
The ZRANGE command offers a wide range of optional arguments, and we will use the WITHSCORES argument with the above command to display the associated scores for each member.
Assume that the players have been playing the game for some hours and scores have increased from 0. Redis ZSETs provide the ZINCRBY command to increment the scores of each member as follows.
This should increment the value of the member bob from 0 to 100. Let’s call the same command to increment the scores of other players as well.
ZINCRBY Pokemon:Leaderboard 76 zakariah
ZINCRBY Pokemon:Leaderboard 450 mary
ZINCRBY Pokemon:Leaderboard 167 john
As per the return values, scores should have been updated properly. Let’s use the ZRANGE command one time to retrieve the members again with their scores.
Bravo! Players’ scores have been properly updated. Furthermore, the members are ordered by their scores in ascending order which is a cool feature of Redis ZSETs.
It is a must to display the rank of each player on a leaderboard. So, the ZREVRANK command is used to show the rank of members where the element associated with the highest score will be the 0th rank, and next highest will be the 1st rank, and so on.
Since member mary has the highest score, that element should be ranked as the top member with 0th rank. Let’s use the ZREVRANK command as follows.
As expected, the rank is 0, which means the top player in the game leaderboard.
Let’s use the ZREVRANK command with the element zakariah as follows. Ideally, it should be the last rank since this member has the lowest score value.
Whenever we need to remove an element or multiple elements from a ZSET, the ZREM command is useful. Let’s remove zakariah from the leaderboard due to his low score.
It has been properly removed from the ZSET.
Most importantly, the ZSET commands have O(log(N)) time complexity, where N is the number of elements in the sorted set, which is considerably faster. At the same time, the ZRANGE command should be used with care because it has O(log(n) + l), where l is the number of results returned by the command. So, it might cause performance issues when working with larger data sets.
In summary, Redis ZSET is a short name for a sorted set data type that can hold unique members ordered by their score values. As discussed, the ZSET members are non-repeated strings, and score values can be repeated. When multiple members are assigned with the same score value, those members will be ordered lexicographically. ZSETs are a great choice for real-time leaderboards, secondary indexing, and priority queues with higher responsiveness and low latency in memory access. To conclude, several commands are available to add, remove, and query members from a given Redis ZSET with ease.