All Products
Search
Document Center

Tair (Redis® OSS-Compatible):Implement distributed leaderboards by using exZset

Last Updated:Mar 30, 2026

When a single sorted-set key holds hundreds of thousands of members, it becomes a hot key and a large key — both of which degrade performance. The TairJedis client provides a DistributedLeaderBoard class that transparently distributes leaderboard data across multiple sub-leaderboards. One logical key fans out to N sub-leaderboards; rank queries aggregate results across all of them and sum the per-sub-leaderboard ranks to produce each member's final rank. This lets you build leaderboards with more than 100,000 members without managing data sharding yourself.

How precise ranking works

exZset supports two methods for computing ranks in a distributed leaderboard: precise ranking (recommended) and linear interpolation (not yet implemented in exZset).

Precise ranking distributes members across N sub-leaderboards using a Cyclic Redundancy Check (CRC) hash of each member's key. To get the rank of member x, FindRank(x) queries every sub-leaderboard and sums the returned ranks. For example, with three sub-leaderboards and 3,000 members total, if the per-sub-leaderboard ranks for member x are 124, 183, and 156, the final rank is 463. Ranks are exact, and the time complexity to retrieve a rank is m × O(log(N)), where m is the number of sub-leaderboards.

Linear interpolation divides data into score segments, records the member count and highest rank for each segment, and estimates ranks using interpolation. Getting a rank is O(m), but ranks are approximate.

Use precise ranking unless your use case can tolerate estimated ranks. For more information about the exZset commands used in this document, see exZset commands.

Prerequisites

Before you begin, ensure that you have:

  • A Tair instance endpoint, port, and password

  • Java development environment with Maven

Set up the leaderboard

Step 1: Add the Maven dependency

Add the following to your pom.xml:

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

Step 2: Configure and run the leaderboard

The following example creates a distributed leaderboard, adds six members with multi-dimensional scores (gold, silver, and bronze medal counts), and retrieves one member's rank and the overall top three.

import io.valkey.JedisPool;
import io.valkey.JedisPoolConfig;
import com.aliyun.tair.tairzset.*;

public class DistributedLeaderBoardExample {
    // Instance connection settings
    private static final int DEFAULT_CONNECTION_TIMEOUT = 5000;
    private static final int DEFAULT_SO_TIMEOUT = 2000;
    private static final String HOST = "<r-bp1mx0ydsivrbp****.redis.rds.aliyuncs.com>";
    private static final int PORT = 6379;
    private static final String PASSWORD = "<Pass****word>";
    private static final JedisPoolConfig config = new JedisPoolConfig();

    // Leaderboard settings
    private static final int shardKeySize = 10;          // Number of sub-leaderboards
    private static final int pageSize = 10;              // Members per page
    private static final boolean reverse = true;         // true = descending order (highest score first)
    private static final boolean useZeroIndexForRank = false; // false = ranks start from 1

    public static void main(String[] args) {
        JedisPool jedisPool = new JedisPool(config, HOST, PORT, DEFAULT_CONNECTION_TIMEOUT,
                DEFAULT_SO_TIMEOUT, PASSWORD, 0, null);

        // Create the distributed leaderboard
        DistributedLeaderBoard dlb = new DistributedLeaderBoard("distributed_leaderboard", jedisPool,
            shardKeySize, pageSize, reverse, useZeroIndexForRank);

        // Add members with multi-dimensional scores: gold, silver, bronze
        // Members are sorted by gold first, then silver, then bronze
        dlb.addMember("A", 32, 21, 16);
        dlb.addMember("B", 25, 29, 21);
        dlb.addMember("C", 20,  7, 12);
        dlb.addMember("D", 14,  4, 16);
        dlb.addMember("E", 13, 21, 18);
        dlb.addMember("F", 13, 17, 14);

        // Get the rank of member A
        System.out.println(dlb.rankFor("A")); // 1

        // Get the top 3 members
        System.out.println(dlb.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}]
    }
}

Replace the following placeholders with your actual values:

Placeholder Description Example
<r-bp1mx0ydsivrbp****.redis.rds.aliyuncs.com> Instance endpoint r-bp1example.redis.rds.aliyuncs.com
<Pass****word> Instance password Your instance password
Note

The score field in the top() response encodes multi-dimensional values separated by #. For member A, "score":"32#21#16" means 32 gold, 21 silver, and 16 bronze medals.

Parameters

Parameter Type Description Default
shardKeySize int Number of sub-leaderboards. Plan this value upfront — it cannot be scaled out dynamically after the leaderboard is created. 10
pageSize int Number of members per page. 10
reverse boolean Sort order. true sorts in descending order (highest score first). false sorts in ascending order. false
useZeroIndexForRank boolean Rank indexing. true starts ranks from 0. false starts ranks from 1. true

For the full list of available methods, see the com.aliyun.tair.tairzset.DistributedLeaderBoard class in the alibabacloud-tairjedis-sdk Javadoc.

Appendix: Conventional vs. distributed leaderboards

The following table compares time complexity for common operations between a conventional leaderboard (single exZset key) and a distributed leaderboard (m sub-leaderboards).

Note

In the distributed column, m is the number of sub-leaderboards and N is the number of members in a sub-leaderboard.

Operation Conventional implementation Conventional complexity Distributed implementation Distributed complexity
Insert a member EXZADD O(log(N)) Compute target sub-leaderboard with crc(key) & m, then EXZADD O(log(N))
Update a member's score EXZINCRBY O(log(N)) Compute target sub-leaderboard with crc(key) & m, then EXZINCRBY O(log(N))
Remove a member EXZREM O(M\*log(N)) Compute target sub-leaderboard with crc(key) & m, then EXZREM O(log(N))
Count all members EXZCARD O(1) EXZCARD on each sub-leaderboard, then sum O(m)
Count total pages EXZCARD ÷ page size O(1) EXZCARD on each sub-leaderboard, sum, then divide by page size O(m)
Count members in a score range EXZCOUNT O(log(N)) EXZCOUNT on each sub-leaderboard, then merge m × O(log(N))
Remove members in a score range EXZREMRANGEBYSCORE O(log(N)+M) EXZREMRANGEBYSCORE on each sub-leaderboard m × O(log(N))
Get a member's score EXZSCORE O(1) Compute target sub-leaderboard with crc(key) & m, then EXZSCORE O(1)
Get a member's rank EXZRANK O(log(N)) EXZRANKBYSCORE on each sub-leaderboard, then sum m × O(log(N))
Get a member's score and rank EXZSCORE + EXZRANK O(log(N)) 1. Compute target sub-leaderboard with crc(key) & m, then EXZSCORE. 2. EXZRANKBYSCORE on each sub-leaderboard, then sum. m × O(log(N))
Get the top i members EXZRANGE O(log(N)+M) EXZRANGE top i from each sub-leaderboard, then merge m × O(log(N))
Get page i of the leaderboard EXZRANGE O(log(N)) Retrieve all members before the target page from each sub-leaderboard, then sort m × O(log(N))
Set an expiration time EXPIRE O(1) EXPIRE on each sub-leaderboard O(m)
Delete the leaderboard DEL O(N) DEL on each sub-leaderboard m × O(N)