Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Einführung in Redis-Datenstrukturen:Sätze

Redis (Remote Dictionary Server) ist ein äußerst beliebter In-Memory-Schlüsselwertspeicher, der auch optionale Dauerhaftigkeit, Partitionierung, Replikation und eine Vielzahl anderer Funktionen bietet. Es ist derzeit die beliebteste Schlüsselwertdatenbank und ist bekannt für seine Einfachheit, seinen geringen Speicherbedarf und seine niedrige Lernkurve. Redis wird auch als Datenstrukturserver bezeichnet und unterstützt atomare Operationen für Datenstrukturen wie Hashes, Listen, Sätze, sortierte Sätze, Bitmaps und Hyperloglogs. In diesem Beitrag sehen wir uns den von Redis bereitgestellten Set-Datentyp zusammen mit seiner Verwendung und Anwendungsfällen aus dem wirklichen Leben an.

Redis-Sets

Redis-Sätze sind ungeordnete Sammlungen von Zeichenfolgen (eine Zeichenfolge ist der grundlegende Redis-Wert, der fast alles enthalten kann), die eine konstante Zeit zum Hinzufügen, Entfernen und Zugehörigkeitsprüfungen bietet. Redis unterstützt auch relativ schnelle Vereinigungs-, Schnittmengen- und Subtraktionsoperationen zwischen Sätzen. Wie erwartet erlaubt es keine wiederholten Werte.

Hier sind einige Beispiele für Redis-Sets in Aktion von der redis-cli . Hier ist eine Zusammenfassung der Tastendarstellungen im folgenden Beispiel:

  • Benutzer:alle stellt eine Menge aller auf einer Website registrierten Benutzer dar.
  • users:actv steht für aktive Benutzer.
  • users:inactv steht für inaktive Benutzer (Benutzer, die die Website eine Weile nicht besucht haben).
# 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"

Weitere wichtige Set-Befehle sind:

  • SUNION – Vereinigung festlegen
  • SPOP – zufällig ein Element entfernen
  • SREM – ein oder mehrere Elemente entfernen

Die vollständige Liste der satzbezogenen Redis-Befehle finden Sie hier.

Interne Redis

Redis speichert Sätze intern als Wörterbücher. Wörterbücher in Redis sind als Hash-Tabellen implementiert, die die Hash-Funktion MurmurHash2 verwenden und durch inkrementelle Größenanpassung wachsen. Hash-Kollisionen werden durch Verkettung behandelt. Mengen haben eine spezielle Codierung für kleine Mengen, wenn alle Mitglieder einer Menge in Radix 10 im Bereich # von 64-Bit-Ganzzahlen mit Vorzeichen liegen, die als IntSets bezeichnet werden. Dies ist im Wesentlichen ein sortiertes Array von ganzen Zahlen. Suchen innerhalb des Arrays werden durch binäre Suche durchgeführt. Offensichtlich ist diese Implementierung für sehr kleine Mengen effizient. Die Größe, bis zu der diese Kodierung verwendet wird, wird durch set-max-intset-entries geregelt Konfigurationsparameter. Der Standardwert ist 512. Eine gute Beschreibung der von Redis verwendeten internen Datenstrukturen finden Sie hier.

Redis-Anwendungen

Hier ist eine kleine Liste einiger möglicher Redis-Set-Anwendungen:

  • Als Set kann es verwendet werden, um einzigartige Gegenstände zu verfolgen:
    • Alle eindeutigen IP-Adressen, die Ihre Website besuchen.
    • Alle eindeutigen Jobinstanzen, die sich derzeit in einem bestimmten Status befinden usw.
  • Auch hier kann es als Satz verwendet werden, um „gehört zu“ oder eine ähnliche Beziehung zu bezeichnen:
    • Alle SKUs, die zu einer bestimmten Kategorie gehören.
    • Alle Objekte mit einem bestimmten Tag usw.
  • Mengen können nur verwendet werden, um Beziehungen zu kombinieren, d.h. Vereinigung/Schnittmenge/Subtraktion von Mengen:
    • Alle SKUs, die zur Kategorie „T-Shirts“, aber nicht zu einer Unterkategorie „Rollkragenpullover“ gehören.

Lassen Sie uns ein Beispiel aus dem wirklichen Leben aufgreifen und satzbezogene Anwendungsfälle weiter untersuchen.

Visueller Profiler für Ihren eBook-Shop

Nehmen wir an, Sie sind der Eigentümer eines sehr großen Online-Buchladens, der Millionen von Titeln auflistet. Ihre primäre Datenbank ist MongoDB, die für die meisten Ihrer Anwendungsfälle mit der richtigen Verwendung von Indizierung, Sharding usw. recht gut funktioniert. Hier ist ein partielles DB-Dokumentschema für die Bücher Sammlungen:

...
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 ...],
...

Sie zeichnen Transaktionen auch in einer Sammlung namens txns auf was so aussehen kann:

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

Und eine Sammlung für Ansichten namens views:

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

Offensichtlich ist dies ein stark vereinfachtes Beispiel, das von breiten Annahmen ausgeht. Unsere Absicht ist es, ein Redis-Set-Beispiel in einem (fast) realen Szenario zu zeigen.

Ok, jetzt möchten Sie also als Filialleiter ein Visual Profiler-Tool, um die Beziehungen und das Kundenverhalten über verschiedene Kategorien hinweg zu analysieren. Zum Beispiel:

  • Was ist die beliebteste Kategorie?
  • Schauen sich Leute, die Science Fiction anschauen oder kaufen, auch Sachbücher an?

Sie möchten dies in Echtzeit tun können, d. h. die Benutzeroberfläche des Profilers wird Kästchen und Schaltflächen ankreuzen, mit denen Sie Parameter ändern und Ergebnisse (fast) sofort anzeigen können.

Das Durchführen solcher Vorgänge in MongoDB erfordert das Durchführen ziemlich komplizierter Abfragen, um verschiedene Kategorien, Tags und andere Daten zu verknüpfen, die Ihnen wichtig sein könnten. Mit einem Arbeitssatz, der nicht in den Arbeitsspeicher passt, wären dies nicht die schnellsten Operationen. Zum Beispiel:

  • Um alle heute verkauften Bücher zu finden, die Belletristik, aber keine Science-Fiction waren, müssen Sie den txn abfragen Sammlung der heutigen Transaktionen. Dann iterieren Sie über die SKUs, um ihre Kategorien zu sammeln, und führen Sie dann $in/$nin-Operationen durch.

Mal sehen, wie dies gehandhabt würde, wenn man Redis in den Mix einbezieht. Am Ende jedes Tages können täglich geplante Jobs über diese MongoDB-Sammlungen laufen, um Redis-Sätze zu erstellen. Die Art der Sets, die Sie erstellen möchten, hängt von der Art der Filter ab, die Sie auf Ihrem Frontend unterstützen möchten. Angenommen, Sie möchten kategoriebezogene Suchanfragen unterstützen, dann möchten wir Sets erstellen wie:

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
...

Die cat:sku:*-Sets enthalten SKUs von Büchern, die heute in dieser Kategorie verkauft/angesehen wurden. In ähnlicher Weise enthält cat:cid:* die CID von Kunden, die Bücher in dieser Kategorie gekauft/verkauft haben. Beispiele für Abfragen, die wir mit diesen Sätzen beantworten können, sind:

  • Kunden (oder Anzahl der Kunden), die heute Belletristik (Einzelkategorie) angesehen/gekauft haben:smembers cat:cid:fiction
  • Kunden, die Geschichte angesehen/gekauft haben, aber heute keine Militärgeschichte:sdiff cat:cid:history cat:cid:milhistory
  • (Anzahl der) heute verkauften Bücher, die Science-Fiction und Militär waren, d. h. militärische Science-Fiction:sinter cat:sku:scfiction cat:sku:military
  • Jede beliebige Anzahl solcher Vereinigungs-, Schnittmengen- und Differenzoperationen, die Ihnen wichtig sind.

Dies selbst gibt uns sehr leistungsfähige Abfragemöglichkeiten. Lass uns weitere Sets hinzufügen! Angenommen, wir erstellen zusätzliche Sets basierend auf Buchbewertungen. Zum Beispiel:

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: ...
..

Ausgestattet mit diesen Sets können Sie jetzt schnell Dinge herausfinden wie:

  • Heute gekaufte Belletristikbücher mit mindestens 4 Sternen:  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:fiction
  • Kunde, der Bücher mit 3 Sternen und mehr in der Geschichte gekauft hat:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:history rat:cid:5strabv

Nehmen wir nun an, Sie möchten allen Ihren Kunden, die heute ein Astrologiebuch mit einer Bewertung von 2 oder darunter gekauft haben, einen Rabattgutschein senden (als Entschuldigung für die schlechte Erfahrung dieses Buch lesen zu müssen!). Sie können diese Liste von CustomerID exportieren s aus und senden Sie es an Ihre E-Mail-Anwendung. Ebenso könnten Sie Sätze für andere Dinge erstellen, die Sie möglicherweise als Filter in Ihrem Visual Profiler anzeigen möchten, z. B. Tags, Preisspannen usw.

Die Vorteile der Verwendung von Redis-Sets liegen hier auf der Hand. Der In-Memory-Speicher führt zu einem wirklich schnellen Zugriff, sodass sich das Frontend bissig anfühlt. Darüber hinaus sind Redis-Set-Operationen entweder zeitkonstant oder linear.

Schlussfolgerung

In diesem Beitrag haben wir mit Beispielen eine der nützlichsten Redis-Datenstrukturen vorgestellt:Sets. Hier sind einige unserer anderen Beiträge in der Reihe Redis-Datenstrukturen:

  • Redis-Hashes
  • Redis-Bitmaps
  • Redis-Sets
  • Sortierte Redis-Sätze