TairZset is a data structure developed by Alibaba Cloud. It allows you to sort score data of the DOUBLE type with respect to 256 dimensions.

Issues with Redis ZSET

The Sorted Set (or ZSET) data structure of open source Redis allows you to sort elements in a single dimension based on the DOUBLE-typed score data. For example, you can use the IEEE Standard for Floating-Point Arithmetic (IEEE 754) standard to concatenate score data to implement multidimensional sorting. However, this method is limited by complex logic, reduced precision, and the unavailability of the ZINCRBY command.

Introduction to TairZset

To help you implement multidimensional sorting, Alibaba Cloud developed the TairZset data structure. Compared with the preceding method, TairZset provides the following advantages:
  • Allows DOUBLE-typed scores to be sorted based on a maximum of 256 dimensions. The scores are displayed from left to right based on their priorities.

    In a multidimensional sorting, a left score has higher priority than a right score. Take the comparison of three-dimensional scores in the score1#score2#score3 format as an example. TairZset compares the score1s of multiple three-dimensional scores and moves on to score2s only when score1s are equal. If score1s are not equal, the ranking of score1s represents the ranking of the three-dimensional scores involved. By the same logic, score3s are compared only if score2s are equal. If all score1s are equal and the same holds true for score2s and score3s, the involved multidimensional scores are ranked in ASCII sort order.

    For easier understanding, you can imagine number signs (#) as decimal points (.). This way, 0#99 < 99#90 < 99#99 can be seen as 0.99 < 99.90 < 99.99.

  • Supports the EXZINCRBY command. You no longer need to perform the following operations: retrieve current data, apply the increments to the data, and then write the data back to Redis databases.
  • Supports APIs similar to those available for native Redis ZSET.
  • Allows you to implement regular leaderboards and distributed leaderboards.
  • Supports the open source TairJedis client. For more information about the TairJedis client, visit alibabacloud-tairjedis-sdk. You can use the TairJedis client without the need to encode, decode, or encapsulate data. You can also encapsulate clients for other programming languages by referring to the open source code.
Note For more information about the TairZset commands used in this topic, see TairZset.

Scenarios

The following ranking requirements are common for leaderboards of games, applications, and medals:

  • Support for member query based on the specified score range, create, read, update, delete (CRUD) operations, and reverse sorting.
  • Quick retrieval of sorting results.
  • Scalability to implement distributed leaderboards.Workloads can be offloaded to other data shards when the current data shard has insufficient storage or computing power.

Use TairZset to implement medal leaderboards

Rank Participant Gold medalGold medal Silver medalSilver medal Bronze medalBronze medal
1 A 32 21 16
2 B 25 29 21
3 C 20 7 12
4 D 14 4 16
5 E 13 21 18
6 F 13 17 14

In the medal leaderboard, participants are sorted by the numbers of gold, silver, and bronze medals that they win. If the number of gold medals is the same, they are sorted by the number of silver medals that they win. If the number of silver medals is also the same, they are sorted by the number of bronze medals that they win. For example, Participants E and F have the same number of gold medals, but Participant E has more silver medals than Participant F. In this case, Participant E ranks higher than Participant F. You can use simple API operations to implement this multidimensional sorting with the help of the TairZset data structure.

You can run the following code to install the dependency. Alibaba Cloud SDK for TairJedis is used in this example. For more information, visit alibabacloud-tairjedis-sdk.

<dependency>
    <groupId>com.aliyun.tair</groupId>
    <artifactId>alibabacloud-tairjedis-sdk</artifactId>
    <version>1.6.0</version>
</dependency>

Sample code:

JedisPool jedisPool = new JedisPool();
// Create a leaderboard.
LeaderBoard lb = new LeaderBoard("leaderboard", jedisPool, 10, true, false);

// Rank the participants by the number of their gold medals. If the number of gold medals is the same, rank the participants by the number of their silver medals. If the number of silver medals is also the same, rank the participants by the number of their bronze medals.
//                    Gold medal Silver medal Bronze medal
lb.addMember("A",     32,  21, 16);
lb.addMember("D",     14,  4,  16);
lb.addMember("C",     20,  7,  12);
lb.addMember("B",     25,  29, 21);
lb.addMember("E",     13,  21, 18);
lb.addMember("F",     13,  17,  14);

// Retrieve the rank of Participant A.
lb.rankFor("A"); // 1

// Retrieve the top 3 participants.
lb.top(3);
// [{"member":"A","score":"32#21#16","rank":1}, 
// {"member":"B","score":"25#29#21","rank":2}, 
// {"member":"C","score":"20#7#12","rank":3}]

// Retrieve the entire leaderboard.
lb.allLeaders();
// [{"member":"A","score":"32#21#16","rank":1}, 
// {"member":"B","score":"25#29#21","rank":2}, 
// {"member":"C","score":"20#7#12","rank":3}, 
// {"member":"D","score":"14#4#16","rank":4}, 
// {"member":"E","score":"13#21#18","rank":5}, 
// {"member":"F","score":"13#17#14","rank":6}]

Use TairZset to implement leaderboards by hour, day, week, or month or in real time

If you want to implement a monthly leaderboard for a key, the month information must be used as the index.

Leaderboards for a variety of time ranges can be implemented by using multi-level indexing provided by the TairZset data structure. In this example, all data of the month is stored in a key named julyZset. The following code shows how to write the sample data to the key:

EXZINCRBY julyZset 7#2#6#16#22#100 7#2#6#16#22_user1
EXZINCRBY julyZset 7#2#6#16#22#50 7#2#6#16#22_user2
EXZINCRBY julyZset 7#2#6#16#23#70 7#2#6#16#23_user1
EXZINCRBY julyZset 7#2#6#16#23#80 7#2#6#16#23_user1
Note
  • 7#2#6#16#22#100 indicates that the score is updated to 100 at 16:22 on 6 July. The date belongs to the second week of July.
  • 7#2#6#16#22_user1 indicates the user whose score was updated at this point in time. A prefix indicates that time is added to the username.
Leaderboard type Command and output
Real-time hourly leaderboard. This type of leaderboards includes the members whose scores were updated within an hour before the current time. For example, the current time is 16:23, the leaderboard includes members whose scores were updated within the range of 15:23 to 16:23.
Note If the ranking results are frequently accessed, we recommend that you cache the results.

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#16#23#0 7#2#6#15#23#0

Output:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2"
Leaderboard for a specific hour. For example, you can query the leaderboard that includes the members whose scores are updated within the time range of 16:00 to 17:00.

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#17#0#0 7#2#6#16#0#0

Output:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2"
Daily leaderboard. For example, you can query the leaderboard whose data was generated on July 5.

Before the query, use the following command to insert a data record that was generated on July 5:

EXZINCRBY julyZset 7#2#5#10#23#70 7#2#5#10#23_user1

Output:

"7#2#5#10#23#70"

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#0#0#0 7#2#5#0#0#0

Output:

1) "7#2#5#10#23_user1"
Weekly leaderboard. For example, you can query the leaderboard for the second week of July.

Command:

EXZREVRANGEBYSCORE julyZset 7#3#0#0#0#0 7#2#0#0#0#0

Output:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2"
3) "7#2#5#10#23_user1"
Monthly leaderboard. For example, you can query the leaderboard of July.

Before the query, insert a data record that was generated on July 20.

EXZINCRBY julyZset 7#4#20#12#20#50 7#4#20#12#20_user1

Output:

"7#4#20#12#20#50"

Command:

EXZREVRANGEBYSCORE julyZset 7#6#0#0#0#0 7#0#0#0#0#0

Output:

1) "7#4#20#12#20_user1"
2) "7#2#6#16#22_user1"
3) "7#2#6#16#22_user2"
4) "7#2#5#10#23_user1"