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

Issues with Redis ZSET

The Sorted Set data structure of open source Redis, which is also known as ZSET, allows you to sort elements only in one dimension based on the DOUBLE-typed score data. It is difficult to use the ZSET data structure to sort data from multiple dimensions. 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 has limits, such as complex logic, reduced precision, and unavailability of the ZINCRBY command.

Introduction to TairZset

Alibaba Cloud developed the TairZset command to solve these issues and implement multidimensional sorting. Compared with the traditional method to implement multidimensional sorting, TairZset provides the following benefits:
  • Supports multidimensional sorting of DOUBLE type data. The scores are sorted from left to right based on their priorities.
  • Supports the ZINCRBY command. You no longer need to retrieve current data, apply the increments to the data, and then write the data into Redis databases.
  • Supports API operations similar to those available for Redis ZSET.
  • Is easy to implement on the client side without the need to encode, decode, or encapsulate the data.
  • Supports regular leaderboards and distributed leaderboards.
Note For more information about the TairZset commands used in this topic, see TairZset commands.

Scenarios

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

  • Support for create, read, update, delete (CRUD) operations, reverse sorting, and member query based on the specified score range.
  • 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 implement this multidimensional sorting by using simple APIs 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);

// If the number of gold medals that participants win is the same, participants 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.
//                    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 of various 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 is updated at this point in time. A prefix that indicates time is added to the username.
Leaderboard type Command and output
Real-time hourly leaderboard. This type of leaderboards includes the members whose scores are updated within an hour before the current time. For example, the current time is 16:23, the leaderboard includes the members whose scores are updated within the range of 15:23 to 16:23.
Note If the ranking results are frequently accessed, you can cache the ranking results.

Query 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.

Query 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 on July 5.

Before the query, insert a data record that is 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"

Query 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.

Query 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 is 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"

Query 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"