Redis
 sql >> Base de données >  >> NoSQL >> Redis

Introduction aux structures de données Redis :ensembles

Redis (Remote Dictionary Server) est un magasin clé-valeur en mémoire immensément populaire qui fournit également une durabilité, un partitionnement, une réplication facultatifs et une foule d'autres fonctionnalités. Il s'agit actuellement de la base de données de valeurs-clés la plus populaire et est connue pour sa simplicité, sa faible empreinte mémoire et sa faible courbe d'apprentissage. Redis est également appelé serveur de structure de données et prend en charge les opérations atomiques sur les structures de données telles que les hachages, les listes, les ensembles, les ensembles triés, les bitmaps et les hyperloglogs. Dans cet article, nous examinerons le type de données défini fourni par Redis, ainsi que son utilisation et les cas d'utilisation réels.

Ensembles Redis

Les ensembles Redis sont des collections de chaînes non ordonnées (une chaîne est la valeur Redis de base qui peut contenir presque n'importe quoi) qui fournit des vérifications d'ajout, de suppression et d'adhésion à temps constant. Redis prend également en charge les opérations d'union, d'intersection et de soustraction raisonnablement rapides entre les ensembles. Comme prévu, il n'autorise pas les valeurs répétées.

Voici quelques exemples d'ensembles Redis en action à partir de redis-cli . Voici un résumé des représentations clés dans l'exemple ci-dessous :

  • utilisateurs :tous représente un ensemble de tous les utilisateurs enregistrés sur un site Web.
  • utilisateurs :actv représente les utilisateurs actifs.
  • utilisateurs :inactv représente les utilisateurs inactifs (utilisateurs qui n'ont pas visité le site depuis un certain temps).
# sadd key member [member ...] : add members to a set
127.0.0.1:6379> sadd users:all 11 12 13 14 15 Rocket Pocket Socket
(integer) 8
127.0.0.1:6379> type users:all
set
# smembers key: get all members of a set
127.0.0.1:6379> smembers users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "Rocket"
7) "12"
8) "15"
# sismember key member: is the given value a member of the set?
127.0.0.1:6379> sismember users:all 00
(integer) 0
127.0.0.1:6379> sismember users:all 11
(integer) 1
127.0.0.1:6379> sismember users:all Socket
(integer) 1
127.0.0.1:6379> sadd users:inactv 11 12 13
(integer) 3
# sinter key [key ...]: Intersection of multiple sets
# Similar: sinterstore stores the result of intersection of sets to a new set
127.0.0.1:6379> sinter users:all users:inactv
1) "11"
2) "12"
3) "13"
# scard key: cardinality of the set i.e. number of members present in the set
127.0.0.1:6379> scard users:all
(integer) 8
# sdiff key [key ...] : Subtract multiple sets
# Similar: sdiffstore: subtract and store result in a new destination set
127.0.0.1:6379> sdiff users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "12"
7) "Rocket"
8) "15"
127.0.0.1:6379> sdiff users:all users:inactv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
# sdiffstore destination key [key ...]
127.0.0.1:6379> sdiffstore users:actv users:all users:inactv
(integer) 5
127.0.0.1:6379> smembers users:actv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
127.0.0.1:6379> sdiff users:all users:actv users:inactv
(empty list or set)
# smove source destination member: move a member from source set to destination.
127.0.0.1:6379> smove users:inactv users:actv 11
(integer) 1
127.0.0.1:6379> smembers users:actv
1) "Pocket"
2) "11"
3) "Socket"
4) "14"
5) "Rocket"
6) "15"

Les autres commandes d'ensemble importantes incluent :

  • SUNION – ensemble union
  • SPOP – supprimer un élément au hasard
  • SREM – supprimer un ou plusieurs éléments

La liste complète des commandes Redis liées à l'ensemble peut être trouvée ici.

Les composants internes de Redis

Redis stocke en interne les ensembles sous forme de dictionnaires. Les dictionnaires dans Redis sont implémentés sous forme de tables de hachage qui utilisent la fonction de hachage MurmurHash2 et se développent via un redimensionnement incrémentiel. Les collisions de hachage sont gérées par chaînage. Les ensembles ont un codage spécial pour les petits ensembles lorsque tous les membres d'un ensemble sont en base 10 dans la plage # d'entiers signés 64 bits appelés IntSets. Il s'agit essentiellement d'un tableau trié d'entiers. Les recherches dans le tableau sont effectuées par recherche binaire. Évidemment, cette implémentation est efficace pour de très petits ensembles. La taille jusqu'à laquelle cet encodage est utilisé est régie par set-max-intset-entries paramètre de configuration. La valeur par défaut est 512. Une bonne description des structures de données internes utilisées par Redis peut être trouvée ici.

Applications Redis

Voici une petite liste de quelques-unes des applications Redis Set possibles :

  • En tant qu'ensemble, il peut être utilisé pour suivre des éléments uniques :
    • Toutes les adresses IP uniques visitant votre site.
    • Toutes les instances de tâches uniques actuellement dans un état donné, etc.
  • Encore une fois, en tant qu'ensemble, il peut être utilisé pour désigner comme "appartient à" ou une relation similaire :
    • Tous les SKU appartenant à une catégorie particulière.
    • Tous les objets avec une balise particulière, etc.
  • Les ensembles ne peuvent être utilisés que pour combiner des relations, c'est-à-dire l'union/l'intersection/la soustraction d'ensembles :
    • Tous les SKU appartenant à la catégorie des t-shirts, mais pas à une sous-catégorie des cols polo.

Prenons un exemple concret et explorons plus en détail les cas d'utilisation liés à l'ensemble.

Visual Profiler pour votre boutique de livres numériques

Imaginons que vous êtes le propriétaire d'une très grande librairie en ligne qui répertorie des millions de titres. Votre base de données principale est MongoDB et elle fonctionne assez bien pour la plupart de vos cas d'utilisation avec l'utilisation correcte de l'indexation, du sharding, etc. Voici un schéma partiel de document DB pour les livres collecte :

...
sku: SKU,
pid: Product ID,
title: String,
auth: String,
pub: String,
isbn: ISBN,
edition: Int,
price: Float,
rating: Float,
cats: [String, String ...],
tags: [String, String ...],
...

Vous enregistrez également les transactions dans une collection appelée txns qui peut ressembler à :

txnid: TxnID,
cid: CustomerID,
amnt: Float,
curr: Currency,
sku: [sku1, sku2, ...],
time: TimeStamp,
...

Et, une collection de vues appelée vues :

time: TimeStamp, # daily aggregated
cid: CustomerID,
sku: [sku1, sku2, ...],
...

Évidemment, il s'agit d'un exemple très simplifié qui fait des hypothèses générales. Notre intention est de montrer un exemple d'ensemble Redis dans un scénario (quasi) réel.

Ok, alors maintenant, en tant que responsable de magasin, vous voulez un outil Visual Profiler pour analyser les relations et le comportement des clients dans différentes catégories. Par exemple :

  • Quelle est la catégorie la plus populaire ?
  • Les gens qui regardent ou achètent-ils de la science-fiction regardent-ils également de la non-fiction ?

Vous voulez pouvoir le faire en temps réel, c'est-à-dire que l'interface utilisateur du profileur cochera des cases, des boutons vous permettant de modifier les paramètres et affichera les résultats (presque) immédiatement.

Réaliser de telles opérations sur MongoDB impliquera d'effectuer des requêtes plutôt complexes pour joindre diverses catégories, balises et autres données qui pourraient vous intéresser. Avec un ensemble de travail qui ne tient pas en mémoire, ces opérations ne seraient pas les plus rapides. Par exemple :

  • Pour trouver tous les livres vendus aujourd'hui qui étaient de la fiction, mais pas de la science-fiction, il faudra interroger le txn collecte des transactions du jour. Ensuite, itérer sur les SKU pour collecter leurs catégories, puis effectuer des opérations $in/$nin.

Voyons comment cela serait géré en intégrant Redis dans le mix. À la fin de chaque journée, des tâches planifiées quotidiennes peuvent s'exécuter sur ces collections MongoDB pour créer des ensembles Redis. Le type d'ensembles que vous souhaitez créer dépendra du type de filtres que vous souhaitez prendre en charge sur votre interface. Par exemple, supposons que vous souhaitiez prendre en charge les requêtes liées aux catégories, nous souhaitons créer des ensembles tels que :

cat:type:catID
cat:sku:fiction
cat:sku:nonfiction
cat:sku:scfiction
cat:sku:history
cat:sku:milhistory
cat:sku:military
...
cat:cid:fiction
cat:cid:nonfiction
cat:cid:scfiction
cat:cid:history
cat:cid:milhistory
cat:cid:military
...

Les ensembles cat:sku:* contiendront les SKU des livres vendus/consultés aujourd'hui dans cette catégorie. De même, cat:cid:* contiendra le CID des clients qui ont acheté/vendu des livres dans cette catégorie. Voici un exemple de requêtes auxquelles nous pouvons répondre avec ces ensembles :

  • Clients (ou nombre de clients) qui ont consulté/acheté des livres de fiction (catégorie unique) aujourd'hui :smembers cat:cid:fiction
  • Clients ayant consulté/acheté History mais pas Military History aujourd'hui :sdiff cat:cid:history cat:cid:milhistory
  • (Nombre de) livres vendus aujourd'hui qui étaient de la science-fiction et de la science-fiction militaire, c'est-à-dire de la science-fiction militaire :sinter cat:sku:scfiction cat:sku:military
  • N'importe quel nombre d'opérations d'union, d'intersection et de différence dont vous vous souciez.

Ceci nous donne en soi des capacités d'interrogation très puissantes. Ajoutons plus d'ensembles ! Supposons que nous créons des ensembles supplémentaires en fonction des notes des livres. Par exemple :

rat:sku:5str: Set of books with ratings > 4.5
rat:sku:4str: Set of books with ratings > 3.5 && <= 4.5
rat:sku:3str: ...
rat:sku:2str: ...
...
rat:cid:5str: Set of customer who bought books with ratings as mentioned above.
rat:cid:4str: ...
..

Équipé de ces ensembles, vous êtes maintenant en mesure de découvrir rapidement des choses comme :

  • Livres de fiction classés 4 étoiles et plus achetés aujourd'hui :  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:fiction
  • Client ayant acheté des livres d'histoire classés 3 étoiles et plus :sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:historique rat:cid:5strabv

Maintenant, supposons que vous souhaitiez envoyer un bon de réduction à tous vos clients qui ont acheté un livre d'astrologie aujourd'hui avec une note de 2 ou moins (en guise d'excuse pour la mauvaise expérience d'avoir à lire ce livre !). Vous pouvez exporter cette liste de CustomerID s out et envoyez-le à votre application de messagerie. De même, vous pouvez créer des ensembles pour d'autres éléments que vous souhaitez exposer en tant que filtres dans votre Visual Profiler, tels que des balises, des fourchettes de prix, etc.

Les avantages de l'utilisation des ensembles Redis sont ici évidents. Le magasin en mémoire conduira à un accès très rapide afin que l'interface soit rapide. De plus, les opérations d'ensemble Redis sont soit en temps constant, soit linéaires.

Conclusion

Dans cet article, nous avons présenté avec des exemples l'une des structures de données Redis les plus utiles :les ensembles. Voici certains de nos autres articles de la série sur les structures de données Redis :

  • Hachages Redis
  • Bitmaps Redis
  • Ensembles Redis
  • Ensembles triés Redis