Beherrschung von Redis GET und SET: Grundlegende Datenoperationen
Meistern Sie die Grundlagen der Redis-Datenverwaltung mit diesem umfassenden Leitfaden zu den Befehlen `GET` und `SET`. Lernen Sie die grundlegende Speicherung und Abfrage von Zeichenfolgen sowie wichtige erweiterte Optionen wie atomares Setzen (`NX`/`XX`) und integrierte Schlüsselablaufzeiten (`EX`/`PX`) kennen. Entdecken Sie, wie diese grundlegenden Befehle für den Aufbau leistungsstarker Caching-Schichten entscheidend sind.
Beherrschung von Redis GET und SET: Grundlegende Datenoperationen
Redis GET und SET sehen fast zu einfach aus. Einen Wert schreiben. Einen Wert lesen. In realen Anwendungen stecken diese beiden Befehle hinter Login-Sitzungen, Feature-Flags, Ratenbegrenzungen, Cache-Einträgen, kurzlebigen Sperren und "Bitte nicht erneut die Datenbank abfragen"-Abkürzungen.
Die Details sind wichtig, weil Redis genau das tut, was Sie verlangen. Wenn Sie versehentlich einen Schlüssel überschreiben, wird Redis nicht fragen, ob Sie das beabsichtigt haben. Wenn Sie bei Cache-Daten eine Ablaufzeit vergessen, können diese länger leben als die Datenquelle. Wenn Sie einen fehlenden Schlüssel wie eine leere Zeichenfolge behandeln, könnte Ihre Anwendung die falsche Entscheidung treffen.
Das Redis-Schlüssel-Wert-Modell
Bevor wir in die Befehle eintauchen, ist es wichtig, sich daran zu erinnern, dass Redis auf einem einfachen Schlüssel-Wert-Speicher-Modell arbeitet. Jedes Datenelement (der Wert) wird über einen eindeutigen Bezeichner (den Schlüssel) abgerufen. Schlüssel sind Zeichenfolgen, und Werte können verschiedene Datentypen sein (Zeichenfolgen, Listen, Mengen, Hashes usw.). SET und GET befassen sich hauptsächlich mit dem Datentyp String, dem grundlegendsten und am häufigsten verwendeten Typ in Redis.
1. Daten setzen: Der Befehl SET
Der Befehl SET wird verwendet, um einem Schlüssel einen Wert zuzuweisen. Wenn der Schlüssel bereits Daten enthält, überschreibt der Befehl SET den vorhandenen Wert. Die grundlegende Syntax ist unkompliziert.
Grundlegende Syntax und Verwendung
Die einfachste Form erfordert nur den Schlüssel und den Wert:
SET key value
Beispiel: Speichern eines Anzeigenamens eines Benutzers:
127.0.0.1:6379> SET user:100:name "Alice Johnson"
OK
127.0.0.1:6379> GET user:100:name
"Alice Johnson"
Erweiterte SET-Optionen: NX, XX und Ablaufzeit
Die Stärke von SET liegt in seinen optionalen Argumenten, die atomares bedingtes Setzen und Time-to-Live (TTL)-Verwaltung ermöglichen. Diese Optionen sind entscheidend für die korrekte Implementierung von Sperren und Caches.
Bedingtes Setzen: NX und XX
Diese Optionen steuern, wann ein Set-Vorgang stattfindet, und verhindern versehentliche Überschreibungen oder stellen sicher, dass ein Überschreiben nur erfolgt, wenn der Schlüssel existiert.
NX(Nicht vorhanden): Setzt den Schlüssel nur, wenn er nicht bereits existiert. Dies ist nützlich für "Nur erstellen"-Operationen und einfache Sperrmuster.SET my_lock_key some_unique_value NXXX(Vorhanden): Setzt den Schlüssel nur, wenn er bereits existiert. Dies ist nützlich, wenn Sie einen bekannten Schlüssel aktualisieren möchten, ohne versehentlich einen neuen zu erstellen.SET session:token:456 new_value XX
B. Ablaufzeit setzen (TTL)
Um Speicher zu verwalten und zeitbasiertes Caching zu implementieren, können Sie direkt im Befehl SET eine Ablaufzeit festlegen. Dies ist weitaus effizienter, als den Schlüssel zu setzen und dann separat EXPIRE aufzurufen.
EX Sekunden: Setzt die Ablaufzeit in Sekunden.PX Millisekunden: Setzt die Ablaufzeit in Millisekunden.EXAT Zeitstempel: Setzt die Ablaufzeit auf einen bestimmten Unix-Zeitstempel (Sekunden).PXAT Zeitstempel: Setzt die Ablaufzeit auf einen bestimmten Unix-Zeitstempel (Millisekunden).
Beispiel: Setzen eines Schlüssels, der in einer Stunde abläuft:
127.0.0.1:6379> SET cache:product:500 "Product Details" EX 3600
OK
127.0.0.1:6379> TTL cache:product:500
(integer) 3598
Verwenden Sie SET key value EX N oder PX N für Cache-Einträge. Dadurch werden das Schreiben und die Ablaufzeit Teil eines Befehls, was den häufigen Fehler vermeidet, dass die Anwendung einen Cache-Schlüssel schreibt und abstürzt, bevor sie EXPIRE aufruft.
Optionen kombinieren
Alle Optionen können oft für komplexe atomare Operationen kombiniert werden:
# Setzt den Schlüssel nur, wenn er nicht existiert, und lässt ihn in 60 Sekunden ablaufen
SET my_config_setting "active" NX EX 60
2. Daten abrufen: Der Befehl GET
Der Befehl GET ruft den Zeichenfolgenwert ab, der einem bestimmten Schlüssel zugeordnet ist. Es ist eine der schnellsten Operationen, die Redis ausführt, und wird oft in Mikrosekunden abgeschlossen.
Grundlegende Syntax und Verwendung
GET key
Beispiel: Abrufen des gespeicherten Benutzernamens
127.0.0.1:6379> GET user:100:name
"Alice Johnson"
Umgang mit nicht vorhandenen Schlüsseln
Wenn der Schlüssel nicht existiert, gibt GET eine spezielle Antwort zurück, die anzeigt, dass nichts gefunden wurde:
127.0.0.1:6379> GET non_existent_key
(nil)
Im Anwendungscode ist der Erhalt von (nil) die Standardmethode, um festzustellen, dass die Daten fehlen, was normalerweise einen Cache-Fehler auslöst, bei dem die Anwendung die Daten aus der primären Quelle (z. B. einer Datenbank) abrufen und anschließend zurück in Redis schreiben muss.
Einen Wert abrufen und gleichzeitig die Ablaufzeit ändern: GETEX
Der grundlegende Befehl GET gibt nur den Wert zurück. Er gibt nicht die verbleibende TTL zurück. Wenn Sie die TTL benötigen, verwenden Sie TTL key oder PTTL key als separaten Befehl.
GETEX ist anders: Es gibt den Wert zurück und ändert gleichzeitig die Ablaufzeit des Schlüssels. Dies ist nützlich für das Verhalten gleitender Sitzungen, bei dem jedes Lesen die Sitzungslebensdauer verlängert.
GETEX session:abc123 EX 1800
Dies liest den Sitzungswert und setzt die Ablaufzeit auf 30 Minuten zurück. Verwenden Sie dies nicht beiläufig für normale Cache-Lesevorgänge, da jedes Lesen zu einem schreibähnlichen Vorgang wird, der die Schlüsselmetadaten ändert.
3. Praktische Anwendung: Caching mit GET und SET
Der grundlegende Anwendungsfall für GET und SET ist die Implementierung eines einfachen Cache-Aside-Musters.
Schritte in der Anwendungslogik:
- Versuchen Sie
GET product:500. - Wenn Redis einen Wert zurückgibt, decodieren Sie ihn und geben Sie ihn zurück.
- Wenn Redis nil zurückgibt, holen Sie das Produkt aus der primären Datenbank.
- Speichern Sie das serialisierte Ergebnis mit
SET product:500 <json> EX 300. - Geben Sie das Ergebnis an den Aufrufer zurück.
Dieses Muster kann die Datenbanklast reduzieren, erzeugt aber auch ein Fenster für veraltete Daten. Wenn sich das Produkt in der Datenbank ändert, kann Redis den alten Wert weiterhin ausliefern, bis die TTL abläuft oder Ihre Anwendung den Schlüssel ungültig macht. Wählen Sie TTLs basierend darauf, wie falsch die Daten sein dürfen, und nicht nur darauf, wie viel Datenverkehr Sie sparen möchten.
Schlüssel benennen, ohne ein Chaos zu verursachen
Redis erfordert keine Namenskonvention, aber Ihr zukünftiges Ich wird es tun. Ein lesbares Muster wie user:100:name, product:500:summary oder rate:user:100:login macht das Debuggen mit redis-cli viel einfacher.
Halten Sie Schlüssel klar und angemessen kurz. Ein paar Bytes zu sparen, indem Sie einen Schlüssel u:100:n nennen, ist selten die Verwirrung wert, es sei denn, Sie arbeiten in sehr großem Maßstab und haben den Schlüssel-Overhead gemessen. Für die meisten Teams ist Konsistenz wichtiger als extreme Kürze.
Seien Sie vorsichtig mit benutzergelieferten Werten in Schlüsseln. Wenn eine E-Mail-Adresse, URL oder ein Mandantenname Teil des Schlüssels wird, normalisieren Sie ihn zuerst. Andernfalls können kleine Formatierungsunterschiede doppelte Cache-Einträge erzeugen:
[email protected]
[email protected]
[email protected]
Diese können für Ihre Anwendung alle denselben Benutzer darstellen, aber für Redis unterschiedliche Schlüssel.
Überschreibungen, leere Werte und Nil
SET überschreibt standardmäßig:
SET config:mode "safe"
SET config:mode "fast"
GET config:mode
Der endgültige Wert ist "fast". Wenn Überschreiben gefährlich wäre, verwenden Sie NX oder XX.
Unterscheiden Sie auch einen fehlenden Schlüssel von einem leeren Wert. Redis nil bedeutet, dass der Schlüssel fehlt. Eine leere Zeichenfolge ist ein tatsächlich gespeicherter Wert:
SET user:100:nickname ""
GET user:100:nickname
Ihre Client-Bibliothek kann diese unterschiedlich darstellen: null, None, nil, ein leeres Byte-Array oder eine leere Zeichenfolge. Überprüfen Sie das Client-Verhalten, anstatt zu raten.
Sicheres Sperrmuster, mit einer Warnung
Sie werden oft dieses Muster sehen:
SET lock:invoice:123 "worker-7:1700000000" NX EX 30
Es bedeutet "Erstelle diese Sperre nur, wenn sie nicht existiert, und lasse sie nach 30 Sekunden ablaufen." Die Ablaufzeit ist nicht optional. Ohne sie kann ein abgestürzter Worker eine Sperre für immer hinterlassen.
Für einfache Einzelinstanz-Redis-Setups ist dieses Muster oft für die Koordination mit geringem Risiko ausreichend. Für kritisches verteiltes Sperren über Ausfälle, Uhrendrift und mehrere Redis-Knoten hinweg verwenden Sie eine gut bewertete Bibliothek und verstehen Sie deren Kompromisse. Ein Sperrfehler kann zu einem Datenkorruptionsfehler werden.
Debuggen mit redis-cli
Wenn sich ein GET- oder SET-Pfad seltsam verhält, überprüfen Sie den Schlüssel direkt:
redis-cli GET product:500
redis-cli TTL product:500
redis-cli TYPE product:500
TYPE ist nützlich, da GET nur mit Zeichenfolgenwerten funktioniert. Wenn der Schlüssel einen Hash, eine Liste, eine Menge oder eine sortierte Menge enthält, gibt Redis einen Fehler wegen falschen Typs zurück. Das bedeutet normalerweise, dass zwei Teile der Anwendung denselben Schlüsselnamen für unterschiedliche Zwecke verwenden.
Wenn Sie während der Entwicklung mehrere verwandte Schlüssel überprüfen müssen, ist SCAN sicherer als KEYS auf einem stark ausgelasteten Produktionsserver:
redis-cli SCAN 0 MATCH 'product:500:*' COUNT 100
KEYS * kann Redis blockieren, während es den Schlüsselraum durchsucht. Es ist in Ordnung auf einer winzigen lokalen Instanz. Es ist eine schlechte Angewohnheit in der Produktion.
TTLs in realen Systemen auswählen
Die TTL-Wahl ist eine Produkt- und Betriebsentscheidung, kein Redis-Trick. Ein Benutzerprofil-Cache verträgt vielleicht fünf Minuten Veralterung. Eine Berechtigungsprüfung benötigt möglicherweise eine viel kürzere TTL oder explizite Ungültigmachung. Ein Feature-Flag benötigt möglicherweise nahezu sofortige Aktualisierungen, wenn es eine riskante Einführung steuert.
Hier sind drei gängige Muster:
SET cache:product:500 "<json>" EX 300
SET session:abc123 "<json>" EX 1800
SET rate:user:100:login "1" EX 60 NX
Der Produkt-Cache kann etwas veraltet sein. Die Sitzung hat eine klare Lebensdauer. Der Ratenbegrenzungs-Schlüssel verwendet NX, sodass der erste Versuch das Fenster erstellt und spätere Versuche je nach Design verwandte Schlüssel erhöhen oder überprüfen können.
Vermeiden Sie "ewige Cache"-Schlüssel, es sei denn, Sie haben einen klaren Ungültigmachungspfad. Ein ewiger Cache wird schließlich zu einer zweiten Datenbank, normalerweise ohne die betriebliche Disziplin, die Sie auf die echte Datenbank anwenden.
Serialisierungsdetails
Redis-Zeichenfolgen sind binärsicher. Sie können JSON, MessagePack, komprimierte Daten, Zähler oder Klartext enthalten. Der Befehl kümmert sich nicht darum. Ihre Anwendung schon.
JSON ist einfach zu überprüfen:
SET product:500 "{\"id\":500,\"name\":\"Desk Lamp\"}" EX 300
Binäre Formate können in einigen Anwendungen Speicherplatz oder CPU sparen, aber sie erschweren das Debuggen im Terminal. Komprimierung kann bei großen, wiederholten Daten helfen, erhöht aber auch die CPU-Kosten und kann die Tatsache verbergen, dass Sie Objekte cachen, die zu groß sind.
Für Zähler lesen Sie nicht mit GET, addieren Sie in der Anwendung und schreiben Sie mit SET, wenn mehrere Clients denselben Schlüssel aktualisieren könnten. Verwenden Sie stattdessen Redis-atomare Zählerbefehle:
INCR page:view:500
EXPIRE page:view:500 86400
Für Zähler mit erstmaligem Schreiben und Ablaufzeit verwenden Sie eine Transaktion oder ein kleines Lua-Skript, wenn Sie striktes Verhalten benötigen. Andernfalls seien Sie sich über die Rennbedingung im Klaren, die Sie akzeptieren.
Schlüsselkollisionen vermeiden
Zwei Teams, die dieselbe Redis-Datenbank verwenden, können versehentlich einen Schlüssel wie user:100 wiederverwenden. Ein Team speichert JSON mit SET; ein anderes speichert Felder mit HSET. Das nächste GET gibt einen Fehler wegen falschen Typs zurück, und beide Teams verlieren Zeit.
Namespaces helfen:
shop:prod:user:100:profile
shop:prod:session:abc123
billing:prod:invoice:9001
Sie benötigen keine schmerzhaft langen Schlüssel, aber fügen Sie genügend Kontext hinzu, um Kollisionen zwischen Umgebungen, Diensten und Datentypen zu vermeiden. Wenn Sie Redis über Anwendungen hinweg gemeinsam nutzen, ist eine Namenskonvention Teil der Schnittstelle.
Wann GET und SET nicht verwendet werden sollten
Zeichenfolgen sind der Ausgangspunkt, nicht das gesamte Redis-Modell. Wenn Sie häufig ein Feld innerhalb eines größeren JSON-Blobs aktualisieren, ist ein Hash möglicherweise sauberer:
HSET user:100 name "Alice Johnson" email "[email protected]"
HGET user:100 email
Wenn Sie geordnete Ereignisse benötigen, verwenden Sie Streams oder Listen. Wenn Sie Mitgliedschaftsprüfungen benötigen, verwenden Sie Mengen. Wenn Sie Ranglisten benötigen, verwenden Sie sortierte Mengen. Das Umschreiben einer gesamten serialisierten Zeichenfolge für jede kleine Änderung ist anfangs einfach, kann aber teuer und umständlich werden, wenn das Objekt wächst.
Eine kleine Checkliste vor dem Ausliefern
Bevor Sie einen neuen GET- und SET-Pfad ausliefern, stellen Sie ein paar einfache Fragen.
- Wie lautet der genaue Schlüsselname?
- Können zwei Dienste versehentlich denselben Schlüssel verwenden?
- Sollte der Schlüssel ablaufen?
- Was passiert, wenn Redis nil zurückgibt?
- Ist Überschreiben akzeptabel, oder sollte der Schreibvorgang
NXoderXXverwenden? - Ist der Wert klein genug, um als eine Zeichenfolge gelesen und geschrieben zu werden?
- Können Sie den Wert von
redis-cliaus debuggen, wenn das Produktionsverhalten falsch aussieht?
Diese Fragen fangen die meisten grundlegenden Redis-Zeichenfolgenfehler, bevor sie zu Vorfällen werden. Die Befehlssyntax ist einfach. Der Lebenszyklus um den Schlüssel herum ist der Ort, an dem sich normalerweise Fehler verstecken.
GET und SET sind kleine Befehle mit viel betrieblichem Gewicht. Verwenden Sie Ablaufzeiten für Cache-Daten, verwenden Sie NX oder XX, wenn Überschreibungen wichtig sind, behandeln Sie nil als separaten Zustand, und halten Sie Schlüsselnamen konsistent genug, dass jemand sie von einem Terminal aus debuggen kann. Sobald sich Zeichenfolgen beengt anfühlen, verschieben Sie verwandte Felder in Hashes und verwenden Sie die Datenstruktur, die zum Zugriffsmuster passt.