Tous les produits
Search
Centre de documentation

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

Dernière mise à jour :Aug 08, 2026

Les ensembles triés natifs de Redis classent les membres selon un score unique, ce qui complique la mise en œuvre de tableaux de médailles, de classements par fenêtre temporelle et d'autres classements multidimensionnels sans recourir à des solutions de contournement. exZset (également appelé TairZset) trie des scores de type double sur jusqu'à 256 dimensions, éliminant ainsi le besoin de concaténation complexe des scores et permettant des incréments atomiques sur toutes les dimensions.

Utilisez exZset lorsque vous devez :

  • Classer les participants selon plusieurs critères simultanément (par exemple, le nombre de médailles d'or, d'argent et de bronze)

  • Interroger des classements sur différentes fenêtres temporelles — horaires, quotidiennes, hebdomadaires ou mensuelles — à partir d'une seule clé

  • Mettre à l'échelle les charges de travail des classements vers des shards supplémentaires lorsque le stockage ou la puissance de calcul est limitée

Pour la référence complète des commandes, consultez les commandes exZset.

Pourquoi utiliser exZset plutôt que Zset natif

L'ensemble trié natif de Redis (Zset) prend en charge le tri selon un score unique de type double. Une solution de contournement courante consiste à concaténer les scores à l'aide de la norme IEEE 754, mais cette approche présente trois inconvénients : une implémentation complexe, une précision réduite et l'impossibilité d'utiliser la commande ZINCRBY.

exZset résout ces trois problèmes :

Fonctionnalité Zset natif Solution de contournement IEEE 754 exZset
Dimensions de tri 1 Multiples (avec perte de précision) Jusqu'à 256
Incrément atomique ZINCRBY Non pris en charge EXZINCRBY
Compatibilité API — — Similaire au Zset natif
Classements distribués Non Non Oui
Client Java — — Open source TairJedis

Comparaison des scores

exZset utilise # comme séparateur de dimension et compare les scores de gauche à droite : il compare d'abord la dimension la plus à gauche, puis passe à la suivante uniquement si les valeurs sont égales. Si toutes les dimensions sont égales, les membres sont triés selon l'ordre ASCII.

Pour un score score1#score2#score3 :

  1. Comparez score1. Si les valeurs diffèrent, cela détermine le classement.

  2. Si score1 est égal, comparez score2. Si les valeurs diffèrent, cela détermine le classement.

  3. Si score2 est également égal, comparez score3.

Considérez # comme une virgule décimale : 0#99 < 99#90 < 99#99 — la dimension la plus à gauche domine toujours.

Créer un tableau de médailles

Un tableau de médailles classe les participants d'abord par médailles d'or, puis d'argent, puis de bronze. Avec exZset, vous encodez le nombre de médailles de chaque participant sous forme de score tridimensionnel (gold#silver#bronze), de sorte que la logique de classement est intégrée à la structure de données elle-même — aucun tri au niveau de l'application n'est requis.

Exemple de données :

Rang Participant **金牌 Or** **银牌 Argent** **铜牌 Bronze**
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

Les participants E et F ont tous deux 13 médailles d'or. E est mieux classé car il possède 21 médailles d'argent contre 17 pour F.

Prérequis

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

  • L'endpoint, le port et le mot de passe d'une instance Tair

  • Le SDK TairJedis ajouté à votre projet

Ajouter la dépendance TairJedis

Ajoutez les lignes suivantes à pom.xml :

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

Insérer et interroger les données du classement

L'exemple suivant utilise la classe LeaderBoard du SDK TairJedis. Le constructeur accepte le nom de la clé, le pool de connexions, la taille de la page et les options de tri.

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

public class LeaderBoardExample {
    // Replace with your instance endpoint and credentials.
    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();

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

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

        // Add members with three-dimensional scores: gold, silver, bronze.
        lb.addMember("A",  32, 21, 16);
        lb.addMember("B",  25, 29, 21);
        lb.addMember("C",  20,  7, 12);
        lb.addMember("D",  14,  4, 16);
        lb.addMember("E",  13, 21, 18);
        lb.addMember("F",  13, 17, 14);

        // Get the rank of A (1-indexed).
        System.out.println(lb.rankFor("A"));
        // 1

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

        // Get the full leaderboard.
        System.out.println(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}]
    }
}

Pour toutes les méthodes disponibles de LeaderBoard, consultez la Javadoc alibabacloud-tairjedis-sdk sous com.aliyun.tair.tairzset.LeaderBoard.

Remarque

Les exemples ci-dessus utilisent Java avec TairJedis. Pour les autres langages, appelez directement les commandes exZset — voir les commandes exZset.

Créer des classements par fenêtre temporelle

Vous pouvez proposer des classements horaires, quotidiens, hebdomadaires et mensuels à partir d'une seule clé en encodant le temps à la fois dans le score et dans le nom du membre. Cette approche utilise la comparaison de gauche à droite d'exZset pour filtrer les entrées par plage de temps à l'aide de EXZREVRANGEBYSCORE.

Conception de la clé et du score

Stockez toutes les données d'un mois dans une seule clé (par exemple, julyZset). Chaque entrée encode le temps sur six dimensions :

score format:  month#week#day#hour#minute#points
member format: month#week#day#hour#minute_username
Dimension Valeur d'exemple Signification
month 7 Juillet
week 2 Deuxième semaine du mois
day 6 6e jour de la semaine
hour 16 16 h 00
minute 22 :22
points 100 Score obtenu à ce moment-là

Le préfixe temporel dans le nom du membre lie chaque entrée à une minute spécifique. Étant donné qu'exZset compare les dimensions de gauche à droite, la définition des dimensions inférieures sur 0 dans EXZREVRANGEBYSCORE crée une borne inférieure inclusive pour toute granularité temporelle — les dimensions les plus à gauche agissent comme filtre principal.

Insérer des données avec EXZINCRBY

Utilisez EXZINCRBY pour ajouter ou incrémenter atomiquement le score d'un membre — aucun cycle lecture-modification-écriture n'est requis.

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

Interroger les classements par fenêtre temporelle

Toutes les requêtes de plage utilisent EXZREVRANGEBYSCORE avec des bornes de score correspondant à la fenêtre temporelle souhaitée.

Classement Plage de scores Commande Sortie
Horaire en temps réel (15 h 23–16 h 23, heure actuelle 16 h 23) Toutes les entrées mises à jour au cours des 60 dernières minutes EXZREVRANGEBYSCORE julyZset 7#2#6#16#23#0 7#2#6#15#23#0 7#2#6#16#22_user1, 7#2#6#16#22_user2
Heure spécifique (16 h 00–17 h 00) Toutes les entrées dans la fenêtre 16 h xx EXZREVRANGEBYSCORE julyZset 7#2#6#17#0#0 7#2#6#16#0#0 7#2#6#16#22_user1, 7#2#6#16#22_user2
Quotidien (5 juillet) Toutes les entrées du 5e jour de la 2e semaine EXZREVRANGEBYSCORE julyZset 7#2#6#0#0#0 7#2#5#0#0#0 7#2#5#10#23_user1
Hebdomadaire (2e semaine de juillet) Toutes les entrées de la 2e semaine EXZREVRANGEBYSCORE julyZset 7#3#0#0#0#0 7#2#0#0#0#0 7#2#6#16#22_user1, 7#2#6#16#22_user2, 7#2#5#10#23_user1
Mensuel (juillet) Toutes les entrées de juillet EXZREVRANGEBYSCORE julyZset 7#6#0#0#0#0 7#0#0#0#0#0 7#4#20#12#20_user1, 7#2#6#16#22_user1, 7#2#6#16#22_user2, 7#2#5#10#23_user1
Remarque

Pour les classements fréquemment consultés, tels que le classement horaire en temps réel, mettez les résultats en cache pour réduire le nombre de requêtes de plage répétées.

Étapes suivantes