In the daily development of some simple activities, I often encounter the need to rank the user’s scores and so on. At this time, we usually choose the ordered set of redis to store the user’s scores, but the way of ranking different scenarios is slightly different. The following is a summary based on our daily development.
Redis ordered set
First, we briefly introduce what is ordered set.
Redis’s Sorted Set is an ordered collection of String types. Collection members are unique, which means that there can be no duplicate data in the collection.
Each element is associated with a double score. Redis ranks the members of a set from small to large by scores.
The members of an ordered set are unique, but scores can be repeated.
Collections are implemented through hash tables, so the complexity of adding, deleting and searching is O (1). The largest number of members in a collection is 2 ^ 32 – 1 (4294967295, each collection can store more than 4 billion members).
Scenario 1: The higher the user scores, the higher the ranking.
This is the simplest basic application scenario, using the following commands and basic operations:
ZADD: Add or to update member scores
Command parameter: ZADD key score member [[score member] [score member]…]
Add one or more member elements and their score values to the ordered set key.
If a member is already a member of an ordered set, update the score value of the member and ensure that the member is in the right place by re-inserting the member element.
The score value can be an integer value or a double-precision floating-point number.
If the key does not exist, create an empty ordered set and perform the ZADD operation.
When the key exists but is not an ordered set type, an error is returned.
// Assuming that user A (user1) has a score of 50 for the current game, then ZADD user_rank 50 user1 // Add user B (user2) current game score is 60, user C (user3) current game score is 70, you can batch operation ZADD user_rank 60 user2 70 user3 /// Add user 2 and user 3 at the same time, the scores are 2 and 3, respectively.
ZREVRANK: Get the current ranking of members
Command parameter: ZREVRANK key member
Returns the ranking of member members in the ordered set key. The ordered integrators are sorted by score value decreasing (from large to small).
The bottom ranking is zero, that is to say, members with the largest score rank zero.
// Get the current ranking of User A ZREVRANK user_rank user1 // user1 currently ranks third, then output 2
ZSCORE: Getting User Ranking
Command parameter: ZSCORE key member
Returns the score value of the member member member in the ordered set key.
If the member element is not a member of the ordered set key, or the key does not exist, return nil.
// Get the current ranking of User A ZSCORE user_rank user1 // user1, with the current score of 50, outputs "50" # Note that the return value is a string
Scenario 2: User games take the shortest time, ranking ahead
This is also the simplest basic application scenario, using commands and basic operations similar to the scenario, except that the commands to get rankings are different:
ZRANK: Get the current ranking of members
Command parameter: ZRANK key member
Returns the ranking of member members in the ordered set key. The ordered integrators are arranged in the order of increasing score value (from small to large).
The bottom ranking is zero, that is to say, members with the smallest Score Rank zero.
How to deal with the same user score in the above two scenarios
If two users score the same, how does redis rank?
In the same score case, redis uses dictionary sort
So what is dictionary sorting? I believe the following figure can answer this question.
In the same score case, redis uses dictionary sort, and the so-called dictionary sort is actually “ABCDEFG”, “123456…” sort, in the same initial case, redis will compare the following letters, or in accordance with the dictionary sort.
Scenario 1: The higher the user’s score, the higher the ranking. If the score is the same, the user who first achieves the score is in front of the ranking.
In this scenario, we need to change the user’s score composition. The specific ideas are as follows:
- With the same score, the timestamp of the user completing the game is added to the composition of the score value.
- Users who first achieve the score are in the front row, that is, the smaller the timestamp is, the higher the score is.
- If we simply put the score structure together by: score +’+ timestamp, because the bigger the score, the higher the front, and the smaller the timestamp, the higher the front, so that the two parts of the judgment rules are opposite, it is impossible to simply combine the two into a user’s score.
- But we can think conversely. We can subtract the time stamp from the same large number MAX (e.g. 5000000000 000). The smaller the time stamp, the greater the difference. So we can change the structure of score to:Fractions +’+ (MAX-timestamp)So we can meet our needs.
- If you use integers as scores, one thing to note is that the largest integer in JS is:
Math. pow (2, 53) – 1// 9007199254740991, 16 digits
The timestamp has taken up 13 digits, so only 3 digits are left for us to save the user’s real score.
So it’s better to use double-precision floating-point type as score
Therefore, the best score structure is: fraction +’.’+ timestamp, which becomes floating-point number.
Scenario 2: The shortest time for the user to complete the game is ahead of the queue. If the time for completing the game is the same, the user who reaches the record first is ahead of the queue.
In this scenario, we also need to change the user’s score composition. The specific ideas are as follows:
- The completion time of the game is the same, and the timestamp of the user completing the game is added to the composition of the score value.
- When the game time is the same, the first step is to reach the front of the record user rank. That is to say, the smaller the timestamp is, the higher the score is.
- The smaller the game time is, the more advanced it is, and the smaller the timestamp is, the more advanced it is. So the two parts of the judgment rules are the same. We can put the two together to form a score:Score +’. ‘+ Time stampthat will do
- The smaller the user score, the higher the ranking of users