Maison >développement back-end >tutoriel php >PHP+Redis a ordonné une collecte pour obtenir une mise à jour en temps réel des classements sur 24 heures
Introduction de base
L'ensemble ordonné Redis, comme un ensemble, est également une collection d'éléments de type chaîne, et les membres en double ne sont pas autorisés.
La différence est que chaque élément est associé à une partition de type double. Redis utilise des scores pour trier les membres de la collection de petit à grand.
Les membres d'un ensemble ordonné sont uniques, mais les partitions peuvent être répétées.
Les ensembles sont implémentés via des tables de hachage, donc la complexité de l'ajout, de la suppression et de la recherche est de O (1). Le nombre maximum de membres dans une collection est de 2^32 - 1^ (4294967295, chaque collection peut stocker plus de 4 milliards de membres).
Un ensemble ordonné est tout d'abord un ensemble, et ses membres sont uniques. Deuxièmement, chaque membre est associé à une partition, afin que les membres puissent être triés en fonction de la partition.
Description des exigences
Imaginez qu'il y ait des millions de données de joueurs dans un jeu si vous devez maintenant établir un top 10 basé sur la valeur d'expérience du joueur Bang. , que feriez-vous? L'approche générale consiste à écrire une instruction SQL similaire à la suivante pour obtenir :
select * from game_socre order by score desc limit 0,20
Cette méthode est réalisable lorsque la quantité de données est petite, mais la vitesse de requête sera plus lente lorsque la quantité de données est grande. , en particulier lorsqu'une requête de table conjointe est requise, la diminution de la vitesse sera encore plus évidente.
Implémentation
À ce stade, vous pouvez envisager d'utiliser redis pour implémenter cette fonction.
Le principal type de données Redis utilisé pour implémenter cette fonction est l'ensemble ordonné redis zset. zset est une extension du type set, qui possède un attribut de séquence de plus que le type d'origine. Cet attribut ajustera automatiquement la valeur de commande à chaque fois que des données sont insérées pour garantir que les valeurs de valeur sont continuellement disposées dans un certain ordre.
Les principales idées d'implémentation sont :
1 Lorsqu'un nouveau joueur participe au jeu, ajoutez un nouvel enregistrement au zset dans redis (le contenu de l'enregistrement dépend des exigences spécifiques) le score est de 0
2. Lorsque la valeur d'expérience du joueur change, modifiez la valeur du score du joueur
3 Utilisez la méthode ZREVRANGE de redis pour obtenir la liste de classement
Retournez. order Dans la clé définie, les membres de la plage spécifiée. Les positions des membres sont classées par ordre décroissant de valeur de score (du plus grand au plus petit). Les membres ayant la même valeur de score sont triés par ordre lexicographique inversé. La commande ZREVRANGE est identique à la commande ZRANGE sauf que les membres sont classés par ordre décroissant de valeur de score.
redis 127.0.0.1:6379> ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN
1. Préparation des données
2 Obtenez le classement top10 (ZREVRANGE est par ordre décroissant, ZRANGE est par ordre croissant)
3. Consultez le classement réel de l'utilisateur ee (ZREVRANK par ordre décroissant, ZRANK par ordre croissant), score en temps réel
Autres besoins
Besoin de mettre en œuvre le dernier classement des points des utilisateurs sur 24 heures et de compter les 10 meilleurs joueurs et points
Mise en œuvre
Principales idées de mise en œuvre Oui :
Utilisez ZADD pour ajouter les informations de score de l'utilisateur par heure, puis utilisez l'union ZUNIONSTORE pour obtenir la somme des scores de jeu sur 24 heures afin d'obtenir le « classement sur 24 heures » ; (Si vous avez une meilleure idée, vous pouvez. Ce serait mieux si vous laissez un message ci-dessous et me donnez quelques conseils)
ZUNIONSTORE destination numkeys key [key ...]
La commande Redis Zunionstore calcule l'union d'un ou plusieurs ensembles ordonnés donnés, où le le nombre de clés données doit être spécifié avec le paramètre numkeys, et l'union (ensemble de résultats) est stockée dans la destination.
Par défaut, le score d'un membre dans l'ensemble de résultats est la somme des scores de ce membre dans tous les ensembles donnés.
Problèmes que vous pouvez rencontrer
1. Le même problème de score
Lorsque Redis rencontre le même score, il suit l'ordre du dictionnaire des membres de l'ensemble. Triage lui-même, voici le tri selon les deux chaînes "user2" et "user3". S'il est trié dans l'ordre inverse, user3 sera naturellement classé en premier. Pour résoudre ce problème, on peut envisager d'ajouter un horodatage au score. La formule de calcul est :
Score avec horodatage = score réel * 10000000000 + (9999999999 – horodatage)
horodatage Nous utilisons Le La fonction time() fournie par le système est le nombre de secondes depuis le 1er janvier 1970. Nous utilisons un horodatage de 32 bits (cela peut durer jusqu'en 2038), car l'horodatage de 32 bits est un entier décimal de 10 chiffres (le maximum valeur 4294967295), nous laissons donc l'horodatage occuper les 10 bits inférieurs (entier décimal), le score réel est agrandi de 10 ^ 10 fois, puis le résultat de l'addition des deux parties est utilisé comme score de zset. Étant donné que nous trions dans l'ordre chronologique inverse, la partie horodatage doit être inversée, c'est pourquoi nous soustrayons l'horodatage de 9999999999. Lorsque nous voulons lire le score réel du joueur, nous supprimons simplement les 10 derniers chiffres.
Au départ, ce plan semble bon, mais il comporte deux problèmes.
Le premier problème est petit. L'utilisation des secondes car l'horodatage peut ne pas être suffisamment différencié. Si deux horodatages avec le même score apparaissent dans la même seconde, le problème précédent se produira toujours. avec une plus grande précision, mais dans les scénarios réels, peu importe qui est devant à la même seconde.
Le deuxième problème est important, car le type fraction de Redis utilise le double, et le nombre à virgule flottante double précision 64 bits n'a que 52 chiffres significatifs, et la plage entière qu'il peut exprimer avec précision est - 2^53 à 2 ^53, qui ne peuvent représenter que jusqu'à 16 entiers décimaux (la valeur maximale est 9007199254740992, en fait, même 16 chiffres ne peuvent pas être entièrement représentés). Cela signifie que si l'horodatage précédent comporte 10 chiffres, le score n'aura que 6 chiffres, ce qui n'est pas suffisant pour certains scores du classement. Nous pourrions envisager de réduire le nombre d'horodatages, par exemple à partir du 1er janvier 2015, mais cela n'ajouterait que quelques chiffres. Ou réduisez la distinction et utilisez les minutes et les heures comme unités d'horodatage.
Si le type de score de Redis est int64, nous n'avons pas les problèmes ci-dessus. En parlant de cela, en fait, Redis devrait vraiment fournir un ZSet supplémentaire de type int64, mais actuellement cela ne peut être qu'un fantasme à moins que vous ne changiez son code source.
Pour plus de connaissances sur PHP, veuillez visiter le Site Web PHP chinois !
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!