Tous les produits
Search
Centre de documentation

Tair (Redis® OSS-Compatible):Implémenter des classements distribués à l'aide d'exZset

Dernière mise à jour :Aug 08, 2026

Lorsqu'une seule clé de type sorted set contient des centaines de milliers de membres, elle devient une clé sensible (hot key) et une clé volumineuse (large key), ce qui dégrade les performances. Le client TairJedis fournit la classe DistributedLeaderBoard qui répartit de manière transparente les données du classement sur plusieurs sous-classements. Une clé logique est ventilée vers N sous-classements ; les requêtes de rang agrègent les résultats de tous les sous-classements et additionnent les rangs par sous-classement pour produire le rang final de chaque membre. Cela vous permet de créer des classements contenant plus de 100 000 membres sans avoir à gérer vous-même le partitionnement des données.

Fonctionnement du classement précis

exZset prend en charge deux méthodes de calcul des rangs dans un classement distribué : le classement précis (recommandé) et l'interpolation linéaire (non encore implémentée dans exZset).

Le classement précis répartit les membres sur N sous-classements à l'aide d'un hachage CRC (Cyclic Redundancy Check) de la clé de chaque membre. Pour obtenir le rang du membre x, FindRank(x) interroge chaque sous-classement et additionne les rangs renvoyés. Par exemple, avec trois sous-classements et 3 000 membres au total, si les rangs par sous-classement pour le membre x sont 124, 183 et 156, le rang final est 463. Les rangs sont exacts et la complexité temporelle pour récupérer un rang est m × O(log(N)), où m représente le nombre de sous-classements.

L'interpolation linéaire divise les données en segments de scores, enregistre le nombre de membres et le rang le plus élevé pour chaque segment, puis estime les rangs par interpolation. L'obtention d'un rang est de complexité O(m), mais les rangs sont approximatifs.

Utilisez le classement précis, sauf si votre cas d'utilisation peut tolérer des rangs estimés. Pour plus d'informations sur les commandes exZset utilisées dans cette rubrique, consultez les commandes exZset.

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

  • Un endpoint, un port et un mot de passe pour l'instance Tair

  • Un environnement de développement Java avec Maven

Configurer le classement

Étape 1 : Ajouter la dépendance Maven

Ajoutez les lignes suivantes à votre fichier pom.xml :

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

Étape 2 : Configurer et exécuter le classement

L'exemple suivant crée un classement distribué, ajoute six membres avec des scores multidimensionnels (nombre de médailles d'or, d'argent et de bronze), puis récupère le rang d'un membre ainsi que le top 3 global.

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}]
    }
}

Remplacez les espaces réservés suivants par vos valeurs réelles :

Espace réservé Description Exemple
<r-bp1mx0ydsivrbp****.redis.rds.aliyuncs.com> Endpoint de l'instance r-bp1example.redis.rds.aliyuncs.com
<Pass****word> Mot de passe de l'instance Votre mot de passe d'instance
Remarque

Le champ score dans la réponse top() encode les valeurs multidimensionnelles séparées par #. Pour le membre A, "score":"32#21#16" signifie 32 médailles d'or, 21 d'argent et 16 de bronze.

Paramètres

Paramètre Type Description Valeur par défaut
shardKeySize int Nombre de sous-classements. Planifiez cette valeur dès le départ, car elle ne peut pas être augmentée dynamiquement après la création du classement. 10
pageSize int Nombre de membres par page. 10
reverse boolean Ordre de tri. true trie par ordre décroissant (score le plus élevé en premier). false trie par ordre croissant. false
useZeroIndexForRank boolean Indexation des rangs. true commence les rangs à 0. false commence les rangs à 1. true

Pour la liste complète des méthodes disponibles, consultez la classe com.aliyun.tair.tairzset.DistributedLeaderBoard dans la Javadoc alibabacloud-tairjedis-sdk.

Annexe : Classements conventionnels vs distribués

Le tableau suivant compare la complexité temporelle des opérations courantes entre un classement conventionnel (une seule clé exZset) et un classement distribué (m sous-classements).

Remarque

Dans la colonne « Distribué », m représente le nombre de sous-classements et N le nombre de membres dans un sous-classement.

Opération Classement conventionnel Classement distribué
Implémentation conventionnelle Complexité conventionnelle Implémentation distribuée Complexité distribuée
Insérer un membre EXZADD O(log(N)) Calculer le sous-classement cible avec crc(key) & m, puis EXZADD O(log(N))
Mettre à jour le score d'un membre EXZINCRBY O(log(N)) Calculer le sous-classement cible avec crc(key) & m, puis EXZINCRBY O(log(N))
Supprimer un membre EXZREM O(M\*log(N)) Calculer le sous-classement cible avec crc(key) & m, puis EXZREM O(log(N))
Compter tous les membres EXZCARD O(1) EXZCARD sur chaque sous-classement, puis somme O(m)
Compter le nombre total de pages EXZCARD ÷ taille de page O(1) EXZCARD sur chaque sous-classement, somme, puis division par la taille de page O(m)
Compter les membres dans une plage de scores EXZCOUNT O(log(N)) EXZCOUNT sur chaque sous-classement, puis fusion m × O(log(N))
Supprimer les membres dans une plage de scores EXZREMRANGEBYSCORE O(log(N)+M) EXZREMRANGEBYSCORE sur chaque sous-classement m × O(log(N))
Obtenir le score d'un membre EXZSCORE O(1) Calculer le sous-classement cible avec crc(key) & m, puis EXZSCORE O(1)
Obtenir le rang d'un membre EXZRANK O(log(N)) EXZRANKBYSCORE sur chaque sous-classement, puis somme m × O(log(N))
Obtenir le score et le rang d'un membre EXZSCORE + EXZRANK O(log(N)) 1. Calculer le sous-classement cible avec crc(key) & m, puis EXZSCORE. 2. EXZRANKBYSCORE sur chaque sous-classement, puis somme. m × O(log(N))
Obtenir les i premiers membres EXZRANGE O(log(N)+M) EXZRANGE des i premiers de chaque sous-classement, puis fusion m × O(log(N))
Obtenir la page i du classement EXZRANGE O(log(N)) Récupérer tous les membres précédant la page cible de chaque sous-classement, puis trier m × O(log(N))
Définir une durée d'expiration EXPIRE O(1) EXPIRE sur chaque sous-classement O(m)
Supprimer le classement DEL O(N) DEL sur chaque sous-classement m × O(N)