


Exemples détaillés de la façon dont Redis implémente les classements et la même fonction de tri des points par temps
Apprentissage recommandé : Tutoriel vidéo Redis
Dans le développement quotidien, nous rencontrons souvent le besoin de trier les scores des utilisateurs, etc., comme le classement de la puissance de combat dans les jeux et dans les activités d'équipe. Il est nécessaire de classer la valeur de la contribution de chaque équipe.Dans WeChat, il est nécessaire de classer le nombre de pas de chaque ami. À ce stade, la collection ordonnée de redis est généralement sélectionnée pour stocker le score de l'utilisateur afin de répondre aux besoins du classement, mais différent La méthode de classement des scènes est également légèrement différente. Ce qui suit est un résumé basé sur mon développement quotidien.
Exigence : Classez la valeur de la contribution de chaque équipe dans l'activité d'équipe.
Ne considérez pas que l'intégrale est la même
L'ensemble trié de Redis est un ensemble ordonné de type String. Les membres de l'ensemble sont uniques, ce qui signifie que les données en double ne peuvent pas apparaître dans l'ensemble.
Chaque élément est associé à une partition de type double. Redis utilise des scores pour trier les membres de la collection du plus petit au plus grand.
Les membres d'un ensemble ordonné sont uniques, mais les scores peuvent être répétés.
Ignorez le cas des mêmes points et implémentez la liste de classement :
// 准备数据,其中value为每个队伍的ID,score为队伍的贡献值 > zadd z1 5 a 6 b 1 c 2 d 10 e (integer) 5 // 分页查询排行榜所有的队伍和贡献值,要使用zrevrange,而不是zrange,贡献值越大越排在前面 > zrevrange z1 0 2 withscores 1) "e" 2) "10" 3) "b" 4) "6" 5) "a" 6) "5" // 增加某个队伍的贡献值 > zincrby z1 3 d "5" > zincrby z1 4 c "5" // 查询排行榜所有的队伍 > zrevrange z1 0 -1 withscores 1) "e" 2) "10" 3) "b" 4) "6" 5) "d" 6) "5" 7) "c" 8) "5" 9) "a" 10) "5" // 查询某个队伍的排名 > zrevrank z1 d (integer) 2
L'implémentation par défaut de Redis consiste à trier les membres avec le même score dans l'ordre du dictionnaire (09, AZ, a~z). c'est donc dans l'ordre inverse. Par conséquent, le tri avec le même score ne peut pas être trié en fonction de la priorité temporelle.
Les mêmes points sont triés par temps et le classement est unique
Dans la mise en œuvre ci-dessus, si la valeur de contribution de deux équipes est la même, c'est-à-dire que la valeur des points est la même, elles ne peuvent pas être classées en fonction du temps.
Nous devons donc concevoir un score = valeur de contribution + horodatage Celui qui a un score plus élevé sera classé en premier. Enfin, la valeur de contribution doit être analysée en fonction du score.
Conception 1
Utilisez des entiers pour stocker les valeurs de score. Le score lui-même dans Redis est de type double, et le nombre entier maximum pouvant être stocké avec précision est 2^53=9007199254740992 (16 bits). Un horodatage précis en millisecondes nécessite 13 chiffres, ne laissant que 3 chiffres pour la valeur de contribution au stockage. Actuellement, si l'heure est précise en secondes, seuls 10 chiffres sont nécessaires, ce qui laisse 6 chiffres pour la valeur de contribution.
Conception générale : les 3 chiffres supérieurs représentent la valeur de la contribution et les 13 chiffres inférieurs représentent l'horodatage.
Si on rassemble simplement la structure du score : Valeur de la contribution * 10^13 + horodatage
, car plus le score est grand, plus il sera proche, et plus l'horodatage est petit, plus il sera proche . De cette façon, les deux parties Les règles de jugement sont opposées et les deux ne peuvent pas être simplement combinées en une partition. 贡献值 * 10^13 + 时间戳
拼凑,因为分数越大越靠前,而时间戳越小则越靠前,这样两部分的判断规则是相反的,无法简单把两者合成一起成为score。
但是我们可以逆向思维,可以用同一个足够大的数Integer.MAX减去时间戳,时间戳越小,则得到的差值越大,这样我们就可以把score的结构改为:贡献值 * 10^13 + (Integer.MAX-时间戳)
,这样就能满足我们的需求了。
设计2
由于redis的score值是double类型,可以使用整数部分存储贡献值,小数部分存储时间戳,同样时间戳的部分使用一个最大值减去它。
这样,整体设计变为:分数=贡献值 + (Integer.MAX-时间戳) * 10^-13
弊端:由于分数值是由两个变量来计算得出,所以在给队伍增加贡献值时,无法简单的使用之前的zincrby来改变score的值了,这样在并发情况下为队伍增加贡献值就会导致score值不准确。
错误情况模拟:
假设现在队伍A的贡献值为10队伍A中的队员X为队伍增加贡献值1,在程序中算出score为11.xxx队伍A中的队员Y为队伍增加贡献值1,在程序中算出score为11.yyy队伍A中的队员X调用redis的zadd命令设置队伍的贡献值为11.xxx队伍A中的队员Y调用redis的zadd命令设置队伍的贡献值为11.yyy最后算出队伍A的贡献值为11,无法保证增加贡献值这一个操作的原子性。
此时需要借助lua脚本来保证计算和设置贡献值这两个操作的原子性:
// 其中KEYS[1]为排行榜key,KEYS[2]为队伍ID // 其中ARGV[1]为增加的贡献值,ARGV[2]为Integer.MAX-时间戳 local score = redis.call('zscore', KEYS[1], KEYS[2]) if not(score) then score=0 end score=math.floor(score) + tonumber(ARGV[1]) + tonumber(ARGV[2]) redis.call('zadd', KEYS[1], score, KEYS[2]) return 1
由于redis中无法使用时间函数,所以(Integer.MAX-时间戳) * 10^-13
Valeur de la contribution * 10. ^13 + (Integer.MAX-timestamp)
, cela peut répondre à nos besoins. Design 2Étant donné que la valeur du score de redis est de type double, vous pouvez utiliser la partie entière pour stocker la valeur de contribution, la partie décimale pour stocker l'horodatage et utiliser une valeur maximale pour la soustraire de la partie du même horodatage. De cette façon, la conception globale devient : Score = valeur de contribution + (Integer.MAX-timestamp) * 10^-13
Inconvénients : Puisque la valeur du score est calculée par deux variables, donc lorsque vous ajoutez une valeur de contribution à l'équipe, vous ne pouvez pas simplement utiliser le zincrby précédent pour modifier la valeur du score. De cette manière, l'ajout d'une valeur de contribution à l'équipe dans des conditions concurrentes entraînera des valeurs de score inexactes. Supposons que la valeur de contribution actuelle de l'équipe A soit de 10. Le joueur X de l'équipe A ajoute 1 valeur de contribution à l'équipe et le score est calculé dans le programme pour être de 11.xxx Joueur Y de l'équipe A ajoute une valeur de contribution à l'équipe 1. Calculez le score dans le programme à 11.yyy. Le joueur yyy a finalement calculé la valeur de contribution de l'équipe A à 11, et l'atomicité de l'opération d'augmentation de la valeur de contribution ne peut pas être garantie. | À ce stade, vous devez utiliser un script Lua pour assurer l'atomicité des deux opérations de calcul et de définition de la valeur de contribution : | Étant donné que la fonction time ne peut pas être utilisée dans redis, (Integer.MAX- timestamp) * 10^- La partie 13 est calculée et transmise par le programme en dehors du script. |
---|---|---|
Ceux avec les mêmes points sont triés par temps et classés en parallèle | Les classements dits ex aequo sont des classements avec la même situation de classement. | Les résultats que nous attendons sont les suivants : |
ID de l'équipe | Valeur de la contribution | Classement |
a | 100 | 1 |
b | 99 | 2 |
c | 99 | 2 |
当然现实中也有排名不跳过的情况,我这里考虑的是排名跳过的情况。
redis中score的设计还是采用上面的分数=贡献值 + (Integer.MAX-时间戳) * 10^-13
,只是在查询排名时需要进行计算。
比如要查上表中队伍b的排名,思路如下:
- 首先查到队伍b的score
- 再查到跟队伍b的score的整数部分相同(也就是贡献值一样),排在第一个的队伍的value(队伍ID)
- 根据上一步得到的队伍ID查询此队伍的排名就是队伍b的排名
使用命令实现上面的步骤如下:
> zscore 排行榜key teamId > zrevrangebyscore(排行榜key, 上一步得到的score+1, 上一步得到的score, limit, 0 , 1) > zrevrank(排行榜key, 上一步得到的teamId)
为了性能考虑,可以使用下面的脚本一次查出来:
// KEYS[1]表示排行榜key // KEYS[2]表示要查询的队伍的ID local rank = 0 local score = redis.call('zscore', KEYS[1], KEYS[2]) if not(score) then score=0 else score=math.floor(score) local firstScore = redis.call('zrevrangebyscore', KEYS[1], score+1, score, 'limit', 0, 1) rank=redis.call('zrevrank', KEYS[1], firstScore[1]) end return {score,rank}
下面附上分页查询排行榜的脚本,假如一页10条,不用下面的脚本需要查询10次上面的脚本,如果连上面的脚本都没有使用的话就要查询30次redis。
// 排行榜key // ARGV[1]分页起始偏移 // ARGV[2]分页结束偏移 local list = redis.call('zrevrange', KEYS[1], ARGV[1], ARGV[2], 'withscores') local result={} local i = 1 for k,v in pairs(list) do if k%2 == 0 then local teamId = list[k-1] local score = math.floor(v) local firstScore = redis.call('zrevrangebyscore', KEYS[1], score+1, score, 'limit', 0, 1) local rank=redis.call('zrevrank', KEYS[1], firstScore[1]) local l = {teamId=teamId, contributionValue=score, teamRank=rank+1} result[i] = l i = i + 1 end end return cjson.encode(result)
此脚本使用了cjson库,返回的是一个json。
推荐学习:Redis视频教程
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Le mode Redis Cluster déploie les instances Redis sur plusieurs serveurs grâce à la rupture, à l'amélioration de l'évolutivité et de la disponibilité. Les étapes de construction sont les suivantes: Créez des instances de redis étranges avec différents ports; Créer 3 instances Sentinel, Moniteur Redis Instances et basculement; Configurer les fichiers de configuration Sentinel, ajouter des informations d'instance Redis de surveillance et des paramètres de basculement; Configurer les fichiers de configuration d'instance Redis, activer le mode de cluster et spécifier le chemin du fichier d'informations de cluster; Créer un fichier nœuds.conf, contenant des informations de chaque instance redis; Démarrez le cluster, exécutez la commande CREATE pour créer un cluster et spécifiez le nombre de répliques; Connectez-vous au cluster pour exécuter la commande d'informations de cluster pour vérifier l'état du cluster; faire

Comment effacer les données Redis: utilisez la commande flushall pour effacer toutes les valeurs de clé. Utilisez la commande flushdb pour effacer la valeur clé de la base de données actuellement sélectionnée. Utilisez SELECT pour commuter les bases de données, puis utilisez FlushDB pour effacer plusieurs bases de données. Utilisez la commande del pour supprimer une clé spécifique. Utilisez l'outil Redis-CLI pour effacer les données.

Pour lire une file d'attente à partir de Redis, vous devez obtenir le nom de la file d'attente, lire les éléments à l'aide de la commande LPOP et traiter la file d'attente vide. Les étapes spécifiques sont les suivantes: Obtenez le nom de la file d'attente: Nommez-le avec le préfixe de "Fitre:" tel que "Fitre: My-Quyue". Utilisez la commande LPOP: éjectez l'élément de la tête de la file d'attente et renvoyez sa valeur, telle que la file d'attente LPOP: My-Queue. Traitement des files d'attente vides: si la file d'attente est vide, LPOP renvoie NIL et vous pouvez vérifier si la file d'attente existe avant de lire l'élément.

L'utilisation de la directive Redis nécessite les étapes suivantes: Ouvrez le client Redis. Entrez la commande (Verbe Key Value). Fournit les paramètres requis (varie de l'instruction à l'instruction). Appuyez sur Entrée pour exécuter la commande. Redis renvoie une réponse indiquant le résultat de l'opération (généralement OK ou -err).

L'utilisation des opérations Redis pour verrouiller nécessite l'obtention du verrouillage via la commande setnx, puis en utilisant la commande Expire pour définir le temps d'expiration. Les étapes spécifiques sont les suivantes: (1) Utilisez la commande setnx pour essayer de définir une paire de valeurs de clé; (2) Utilisez la commande Expire pour définir le temps d'expiration du verrou; (3) Utilisez la commande del pour supprimer le verrouillage lorsque le verrouillage n'est plus nécessaire.

La meilleure façon de comprendre le code source redis est d'aller étape par étape: familiarisez-vous avec les bases de Redis. Sélectionnez un module ou une fonction spécifique comme point de départ. Commencez par le point d'entrée du module ou de la fonction et affichez le code ligne par ligne. Affichez le code via la chaîne d'appel de fonction. Familiez les structures de données sous-jacentes utilisées par Redis. Identifiez l'algorithme utilisé par Redis.

Les causes de la perte de données redis incluent les défaillances de mémoire, les pannes de courant, les erreurs humaines et les défaillances matérielles. Les solutions sont: 1. Stockez les données sur le disque avec RDB ou AOF Persistance; 2. Copiez sur plusieurs serveurs pour une haute disponibilité; 3. Ha avec Redis Sentinel ou Redis Cluster; 4. Créez des instantanés pour sauvegarder les données; 5. Mettre en œuvre les meilleures pratiques telles que la persistance, la réplication, les instantanés, la surveillance et les mesures de sécurité.

Utilisez l'outil de ligne de commande redis (Redis-CLI) pour gérer et utiliser Redis via les étapes suivantes: Connectez-vous au serveur, spécifiez l'adresse et le port. Envoyez des commandes au serveur à l'aide du nom et des paramètres de commande. Utilisez la commande d'aide pour afficher les informations d'aide pour une commande spécifique. Utilisez la commande QUIT pour quitter l'outil de ligne de commande.
