Key-Value und der Cache
Kurz gesagt: Ein Key-Value-Store wie Redis ist ein Wörterbuch im Arbeitsspeicher, das zu einem Schlüssel sehr schnell den Wert liefert. Deshalb eignet er sich als Cache, für Sitzungen und für Zähler.
Problem
Die Seite, die tausendmal dasselbe fragt
Die Startseite des Shops zeigt die drei meistverkauften Produkte. Das ist die Abfrage:
Sie verbindet drei Tabellen und addiert alle Bestellzeilen. Bei 2000 Besuchen pro Minute führt die Datenbank sie 2000-mal aus, obwohl sich die Antwort nur alle paar Stunden ändert. Auch der Warenkorb und der Login fragen bei jeder Seite die Datenbank dasselbe. Du brauchst einen Ort, an dem die fertige Antwort in einem Bruchteil einer Millisekunde geholt wird.
Die Idee
Ein Schlüssel und ein Wert
Eine Key-Value-Datenbank ist ein Wörterbuch: Jeder Wert hat einen Schlüssel, und du bekommst ihn über den Schlüssel. Es gibt keine Tabellen, keine Spalten und keine Abfragen nach dem Wert. Deshalb ist sie so schnell: Redis hält alles im Arbeitsspeicher und antwortet in Mikrosekunden.
Das Feld ist ein Simulator mit den Redis-Befehlen. Schlüssel schreibt man meist mit Doppelpunkten, damit klar ist, was darin steckt:
GET auf einen Schlüssel, den es nicht gibt, liefert (nil). Der Wert ist Text, auch wenn er eine Zahl ist: Die Datenbank weiß nicht, dass 7.90 ein Preis ist.
Probier es aus
Ein Aufrufzähler
INCR erhöht die Zahl in einem Schlüssel um 1 und gibt die neue zurück. Gibt es den Schlüssel nicht, beginnt er bei 0. Zwei Seiten, die gleichzeitig zählen, kommen sich nicht in die Quere: Jeder Befehl in Redis läuft bis zum Ende, bevor der nächste beginnt.
Produkt 7 wurde dreimal angesehen und Produkt 9 einmal. Zähle die Aufrufe in den Schlüsseln views:product:7 und views:product:9.
Lösung
INCR views:product:7
INCR views:product:7
INCR views:product:7
INCR views:product:9
Viermal INCR, dreimal für 7 und einmal für 9. Die Prüfung liest beide Schlüssel auf einmal mit MGET und sieht „3“ und „1“. Mit GET und danach SET mit der neuen Zahl würden zwei Seiten gleichzeitig einen Aufruf verlieren. INCR ist eine einzige Operation.
Die Idee
Ein Cache, der abläuft
Ein Cache ist eine Kopie einer Antwort, deren Berechnung teuer ist. Das Programm schaut zuerst in den Cache. Ist dort nichts, fragt es die Datenbank und legt die Antwort für eine festgelegte Zeit (EX in Sekunden) im Cache ab. Diese Zeit ist die TTL (time to live, Lebensdauer), und TTL zeigt, wie viel noch übrig ist:
Nach 60 Sekunden verschwindet der Schlüssel von selbst, und der nächste Besuch fragt wieder die Datenbank. So ist der Cache nie älter als eine Minute, und die Datenbank führt die Abfrage einmal pro Minute aus, nicht 2000-mal.
Genauer, für Neugierige
SLEEP ist nur ein Befehl des Simulators: Er stellt dessen Uhr vor, damit du nicht wirklich wartest. Im echten Redis vergeht die Zeit einfach. Der Simulator sortiert die Antwort von SMEMBERS und KEYS alphabetisch, während Redis überhaupt keine Reihenfolge verspricht. Und KEYS führt man nicht auf einem echten Server mit Millionen Schlüsseln aus: Der Befehl geht sie alle durch und blockiert jeden anderen Befehl. Dort nimmt man SCAN.
Sieh es dir an
Die veraltete Kopie
Der Preis des Kaffees sinkt von 14,90 € auf 12,90 €. Die Datenbank ist aktualisiert, aber der Cache hält die alte Seite noch 10 Minuten lang:
Das ist der häufigste Fehler mit einem Cache: Die Kopie weicht von der Wahrheit ab. Deshalb löscht das Programm, das das Produkt in der Datenbank ändert, sofort seine Kopie im Cache (DEL). Der nächste Besuch findet nichts, fragt die Datenbank und speichert den neuen Preis. Die TTL bleibt als Sicherheitsnetz, falls du es mal vergisst.
Probier es aus
Ein neuer Preis für den Käse
Im Cache liegen die Seiten des Weißkäses (Produkt 7) und der Butter (Produkt 9). Der Preis des Käses hat sich gerade in der Datenbank geändert. Sorge dafür, dass der nächste Besuch beim Käse den neuen Preis bekommt, ohne die Butter anzufassen.
Lösung
DEL cache:product:7
DEL cache:product:7. FLUSHALL würde den alten Preis auch entfernen, aber alles andere ebenfalls: Die ganze Seite läuft auf einmal zur Datenbank. Und den neuen Preis direkt in den Cache zu schreiben bedeutet zwei Quellen der Wahrheit: Scheitert das Schreiben in die Datenbank, lügt der Cache.
Die Idee
Nicht nur Text
Ein Wert in Redis kann auch eine Struktur sein. Jede hat ihre eigenen Befehle:
- Hash (
HSET,HGET,HINCRBY,HGETALL): Felder unter einem Schlüssel, wie ein Warenkorb mit einem Produkt und einer Menge; - Liste (
LPUSH,LRANGE,LTRIM): geordnete Werte, wie die zuletzt angesehenen; - Sorted Set (
ZADD,ZINCRBY,ZREVRANGE): Mitglieder mit einem Score, danach geordnet, wie eine Bestenliste.
Der Warenkorb von Kunde 42 (Produkt 9, Butter, zwei Stück, und Produkt 5, Milch, eins), der nach einer Woche ohne Aktivität abläuft:
Die letzten drei angesehenen Produkte. LPUSH stellt vorne ein, und LTRIM schneidet alles nach dem dritten ab:
Die im Oktober verkauften Stück, in einer Rangliste:
Bei gleichem Score ordnet Redis die Mitglieder alphabetisch (hier umgekehrt, weil die Bestenliste von oben nach unten geht).
Übung
Eine Sitzung, ein Warenkorb und eine Bestenliste
1. Kunde 42 meldet sich an. Die Seite gibt ihm die Sitzungsnummer 9f2c und merkt sich in Redis, wer er ist.
Speichere die Nummer des Kunden (42) im Schlüssel session:9f2c, sodass die Sitzung nach 30 Minuten von selbst abläuft.
Lösung
SET session:9f2c 42 EX 1800
SET session:9f2c 42 EX 1800: 30 Minuten sind 1800 Sekunden. Eine Sitzung ohne Ablauf bleibt für immer, wenn der Kunde einfach das Fenster schließt, und der Speicher von Redis füllt sich mit toten Sitzungen.
2. Der Warenkorb von Kunde 7 liegt im Hash cart:7: Das Feld ist die Produktnummer, der Wert die Menge.
Kunde 7 legt 2 Packungen Butter (Produkt 9) und 1 Milch (Produkt 5) in den Warenkorb. Dann fügt er noch eine Butter hinzu und entfernt die Milch.
Lösung
HSET cart:7 9 2
HSET cart:7 5 1
HINCRBY cart:7 9 1
HDEL cart:7 5
HSET cart:7 9 2, HSET cart:7 5 1, HINCRBY cart:7 9 1 und HDEL cart:7 5. Übrig bleibt ein Feld: Produkt 9 mit 3 Stück. HINCRBY ändert die Menge an Ort und Stelle, ohne die alte zu lesen.
3. Der Schlüssel rating enthält die Durchschnittsbewertung jedes Produkts.
Zeige die drei Produkte mit der höchsten Bewertung zusammen mit den Bewertungen, von der höchsten abwärts.
Lösung
ZREVRANGE rating 0 2 WITHSCORES
ZREVRANGE rating 0 2 WITHSCORES: vom ersten (0) bis zum dritten (2), in umgekehrter Reihenfolge, mit den Scores. ZRANGE liefert die niedrigsten, und ohne WITHSCORES werden die Bewertungen nicht angezeigt.
Die Idee
Wann Key-Value, wann nicht
Eine Key-Value-Datenbank ist gut, wenn du den Schlüssel immer kennst: ein Cache, Sitzungen, Warenkörbe, Zähler, Rate Limiting („höchstens 5 Anmeldeversuche pro Minute“), Warteschlangen für Aufgaben. Sie ist nicht gut, wenn du nach dem Wert fragst („alle Produkte unter 5 €“), wenn die Daten verbunden sind („die Bestellungen des Kunden mit ihren Produkten“) und wenn ein Verlust nicht in Frage kommt. Deshalb steht sie meist neben der SQL-Datenbank, nicht an ihrer Stelle: Die Datenbank ist die Wahrheit, und Redis ist ihre schnelle Kopie.
Genauer, für Neugierige
Neben Redis (und Valkey, das dazu kompatibel ist) sind Key-Value-Datenbanken zum Beispiel Memcached (nur ein Cache, ohne Strukturen), DynamoDB in AWS (mit einem Schlüssel und einem Sortierschlüssel, auf der Platte, verteilt) und etcd (für Cluster-Einstellungen, mit Fokus auf Konsistenz). Redis hält die Daten auf zwei Arten auf der Platte: ein Snapshot alle paar Minuten (RDB) oder ein Protokoll jedes Befehls (AOF).
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Viele Tabellen und eine Tabelle mit sich selbst verbunden · UPDATE: Werte ändern · Aus dem Code mit der Datenbank verbinden · OLTP und OLAP
- Geht weiter in: Dokumentendatenbanken · Replikation, Sharding und CAP · Wie du eine Datenbank wählst
- Aufgaben zum Thema: Arten von Datenbanken