Diagnose und Behebung langsamer Redis-Abfragen mit dem SLOWLOG-Befehl

Verwenden Sie Redis SLOWLOG, um langsame Befehle zu finden, Schwellenwerte anzupassen, Clients zu überprüfen und teure Zugriffsmuster zu ersetzen.

Diagnose und Behebung langsamer Redis-Abfragen mit dem SLOWLOG-Befehl

Redis ist ein extrem schneller In-Memory-Datenspeicher, der häufig für Caching, Echtzeit-Analysen, Sitzungsverwaltung und Message Brokering verwendet wird. Seine Leistung ist oft entscheidend für die Reaktionsfähigkeit der darauf aufbauenden Anwendungen. Selbst mit der Geschwindigkeit von Redis können jedoch schlecht optimierte Befehle oder unerwartete Last zu langsamen Abfragen führen, die Engpässe verursachen und die Gesamtleistung der Anwendung beeinträchtigen.

Die Identifizierung der Ursache beginnt mit Redis SLOWLOG. Es zeichnet Befehle auf, deren serverseitige Ausführungszeit einen Schwellenwert überschreitet, was Ihnen hilft, teure Befehle wie KEYS, breite LRANGE, große HGETALL oder langsame Lua-Skripte zu finden.

Das Redis SLOWLOG-Feature verstehen

Das SLOWLOG ist ein System, das Abfragen protokolliert, die eine bestimmte Ausführungszeit überschreiten. Es handelt sich im Wesentlichen um ein In-Memory-Protokoll von Befehlen, deren Ausführung länger als ein konfigurierter Schwellenwert gedauert hat. Im Gegensatz zu einem herkömmlichen dateibasierten Protokoll wird SLOWLOG direkt im Arbeitsspeicher von Redis gespeichert, was einen schnellen Zugriff und eine einfache Verwaltung ohne Disk-I/O-Overhead ermöglicht.

Jeder Eintrag enthält eine eindeutige ID, einen Unix-Zeitstempel, die Ausführungszeit in Mikrosekunden, die Befehlsargumente und in modernen Redis-Versionen die Client-Adresse und den Client-Namen, sofern verfügbar. SLOWLOG misst die Befehlsausführung innerhalb von Redis; es umfasst keine Netzwerklatenz, clientseitige Wartezeiten oder die Zeit, die in der Warteschlange verbracht wird, bevor Redis mit der Ausführung des Befehls beginnt.

Wie SLOWLOG funktioniert: Konfigurationsparameter

Bevor Sie SLOWLOG effektiv nutzen können, ist es wichtig, seine beiden primären Parameter zu verstehen und zu konfigurieren. Diese Parameter steuern, was protokolliert wird und wie viele Einträge aufbewahrt werden.

slowlog-log-slower-than

Dieser Parameter definiert den Schwellenwert für die Ausführungszeit (in Mikrosekunden), ab dem ein Befehl protokolliert wird. Nur Befehle, die länger als dieser angegebene Wert dauern, werden im SLOWLOG aufgezeichnet. Wenn Sie diesen Wert zu niedrig ansetzen, werden möglicherweise zu viele Befehle protokolliert, was erheblichen Speicher verbrauchen und die Analyse erschweren kann. Wenn Sie ihn zu hoch ansetzen, übersehen Sie möglicherweise wirklich langsame Abfragen.

  • Standardwert: 10000 (10 Millisekunden)
  • Empfehlung: Beginnen Sie mit dem Standardwert und passen Sie ihn basierend auf den Leistungsanforderungen Ihrer Anwendung an. Für Hochleistungssysteme könnten Sie ihn auf 1000 Mikrosekunden (1 Millisekunde) oder sogar 100 Mikrosekunden senken.
  • Besonderer Wert: Wenn Sie ihn auf 0 setzen, wird jeder Befehl protokolliert. Wenn Sie ihn auf einen negativen Wert setzen, wird SLOWLOG vollständig deaktiviert.

Sie können den aktuellen Wert dieses Parameters anzeigen:

redis-cli config get slowlog-log-slower-than

Um einen neuen Wert festzulegen (z. B. 5000 Mikrosekunden oder 5 Millisekunden):

redis-cli config set slowlog-log-slower-than 5000

Um diese Änderung dauerhaft zu machen, müssen Sie Ihre redis.conf-Datei aktualisieren oder CONFIG REWRITE verwenden, sofern von Ihrer Redis-Version und -Einrichtung unterstützt.

slowlog-max-len

Dieser Parameter gibt die maximale Anzahl von Einträgen an, die Redis im SLOWLOG behält. Wenn das Protokoll seine maximale Länge erreicht, werden neue Einträge dazu führen, dass die ältesten Einträge automatisch entfernt werden (FIFO - First In, First Out).

  • Standardwert: 128 Einträge
  • Empfehlung: Der Standardwert ist für vielbeschäftigte Produktionssysteme oft zu klein. Erwägen Sie, ihn auf 1024 oder sogar 4096 zu erhöhen, um sicherzustellen, dass Sie genügend Verlauf für eine gründliche Analyse erfassen, wobei die Speicherauswirkungen zu berücksichtigen sind.

Sie können den aktuellen Wert anzeigen:

redis-cli config get slowlog-max-len

Um einen neuen Wert festzulegen (z. B. 1024 Einträge):

redis-cli config set slowlog-max-len 1024

Denken Sie auch hier daran, diese Änderung in Ihrer redis.conf-Datei zu speichern.

Abrufen und Analysieren von SLOWLOG-Einträgen

Sobald SLOWLOG konfiguriert ist, können Sie mit einer Reihe von Befehlen darauf zugreifen.

SLOWLOG GET

Dieser Befehl wird verwendet, um Einträge aus dem SLOWLOG abzurufen. Sie können optional eine count-Angabe machen, um eine bestimmte Anzahl der neuesten Einträge abzurufen.

  • SLOWLOG GET: Ruft alle aktuell im Protokoll befindlichen Einträge ab.
  • SLOWLOG GET <count>: Ruft die neuesten <count> Einträge ab.

Beispiel:

# Die 10 neuesten Slow-Log-Einträge abrufen
redis-cli slowlog get 10

Beispielausgabe (zur Verdeutlichung vereinfacht):

1) 1) (integer) 12345        # Eindeutige ID für den Protokolleintrag
   2) (integer) 1678886400   # Unix-Zeitstempel (z. B. 15. März 2023, 12:00:00 UTC)
   3) (integer) 25000        # Ausführungszeit in Mikrosekunden (25 ms)
   4) 1) "LRANGE"           # Der Befehl
      2) "mybiglist"       # Argument 1
      3) "0"               # Argument 2
      4) "-1"              # Argument 3
   5) "127.0.0.1:54321"  # Client-IP und Port
   6) "client-name-app" # Client-Name (falls gesetzt)
...

SLOWLOG LEN

Dieser Befehl gibt die aktuelle Anzahl der Einträge im SLOWLOG zurück.

redis-cli slowlog len

Ausgabe:

(integer) 5

SLOWLOG RESET

Dieser Befehl löscht alle Einträge aus dem SLOWLOG. Dies ist nützlich, nachdem Sie vorhandene Einträge analysiert haben und mit einem frischen Protokoll beginnen möchten, um neue Leistungsdaten zu erfassen.

redis-cli slowlog reset

Ausgabe:

OK

Interpretieren der SLOWLOG-Ausgabe

Jeder Eintrag enthält kritische Informationen:

  1. Eindeutige ID: Ein sequenzieller Identifikator. Nützlich zum Verfolgen bestimmter Ereignisse.
  2. Zeitstempel: Wann der Befehl ausgeführt wurde. Hilft, langsame Abfragen mit Anwendungsbereitstellungsänderungen oder bestimmten Lastperioden zu korrelieren.
  3. Ausführungszeit (Mikrosekunden): Die wichtigste Metrik. Sie sagt Ihnen genau, wie lange der Befehl zur Ausführung benötigt hat. Hohe Werte deuten auf einen potenziellen Engpass hin.
  4. Befehl und Argumente: Der genaue Redis-Befehl und seine Parameter. Dies ist entscheidend, um zu verstehen, welche Operation langsam war (z. B. KEYS *, LRANGE 0 -1 auf einer sehr großen Liste, SORT ohne LIMIT).
  5. Client-Adresse: Die IP-Adresse und der Port des Clients, der den Befehl ausgegeben hat. Hilft, die Quelle der Anwendung oder des Dienstes zurückzuverfolgen.
  6. Client-Name: Wenn Ihre Anwendung CLIENT SETNAME setzt (für eine bessere Beobachtbarkeit sehr zu empfehlen), bietet dies eine zusätzliche Kontextebene, die angibt, welcher Teil Ihrer Anwendung die langsame Abfrage durchgeführt hat.

Praxisbeispiel: Identifizieren eines langsamen Befehls

Lassen Sie uns einen langsamen Befehl simulieren und sehen, wie SLOWLOG ihn erfasst.

Setzen Sie zunächst slowlog-log-slower-than zu Demonstrationszwecken auf einen niedrigen Wert, z. B. 1000 Mikrosekunden (1 Millisekunde):

redis-cli config set slowlog-log-slower-than 1000

Führen Sie als Nächstes eine Operation aus, die bekanntermaßen potenziell langsam ist, wenn sie auf einen großen Datensatz angewendet wird, wie z. B. KEYS * oder ein LRANGE auf eine Liste mit vielen Elementen.

Erstellen wir eine große Liste:

for i in {1..100000}; do redis-cli LPUSH mybiglist $i; done

Führen Sie nun einen LRANGE-Befehl aus, der alle Elemente aus dieser großen Liste abruft:

redis-cli LRANGE mybiglist 0 -1

Dieser Befehl wird wahrscheinlich länger als 1 Millisekunde dauern.

Überprüfen Sie schließlich das SLOWLOG:

redis-cli slowlog get 1

Sie sollten eine Ausgabe ähnlich dieser sehen (Werte variieren):

1) 1) (integer) 12346
   2) (integer) 1678886450
   3) (integer) 15432 # Dies ist unsere langsame Ausführungszeit in Mikrosekunden
   4) 1) "LRANGE"
      2) "mybiglist"
      3) "0"
      4) "-1"
   5) "127.0.0.1:54322"
   6) ""

Die Ausgabe zeigt deutlich den Befehl LRANGE mybiglist 0 -1, seine Ausführungszeit (15432 Mikrosekunden oder 15,432 ms) und wann er aufgetreten ist. Dies sagt uns sofort, dass das Abrufen einer gesamten großen Liste erhebliche Zeit in Anspruch nimmt.

Strategien zur Behebung langsamer Abfragen

Sobald Sie langsame Abfragen mit SLOWLOG identifiziert haben, besteht der nächste Schritt darin, sie zu optimieren. Hier sind gängige Strategien:

  1. Optimieren Sie Datenstrukturen und Zugriffsmuster:

    • Vermeiden Sie O(N)-Befehle auf großen Datensätzen: Befehle wie LRANGE 0 -1 (alle Elemente abrufen), SMEMBERS (alle Set-Mitglieder abrufen), HGETALL (alle Hash-Felder/Werte abrufen), SORT (ohne LIMIT) können langsam sein. Wenn Sie große Sammlungen verarbeiten müssen, ziehen Sie in Betracht, mit SCAN, SSCAN, HSCAN oder ZSCAN zu iterieren, anstatt alles auf einmal abzurufen.
    • Verwenden Sie geeignete Datenstrukturen: Wenn Sie beispielsweise häufig Attribute eines Objekts abrufen müssen, verwenden Sie einen Hash anstatt einzelner Schlüssel für jedes Attribut.
    • Ergebnisse begrenzen: Verwenden Sie für Listen oder sortierte Sets LRANGE <start> <end> oder ZRANGE <start> <end> mit angemessenen Grenzen, anstatt die gesamte Struktur abzurufen.
  2. Pipelining: Anstatt Befehle einzeln zu senden, bündeln Sie mehrere Befehle in einer einzigen Anfrage mit Pipelining. Dies reduziert den Overhead der Netzwerk-Round-Trip-Zeit (RTT), was Anwendungen erheblich beschleunigen kann, selbst wenn einzelne Befehle schnell sind.

    # Ohne Pipelining (langsamer aufgrund mehrerer RTTs)
    r.set('key1', 'value1')
    r.set('key2', 'value2')
    
    # Mit Pipelining (schneller, eine RTT)
    pipe = r.pipeline()
    pipe.set('key1', 'value1')
    pipe.set('key2', 'value2')
    pipe.execute()
    
  3. Lua-Scripting (EVAL): Für komplexe Operationen, die mehrere Redis-Befehle umfassen und atomar oder mit minimalen RTTs ausgeführt werden müssen, sollten Sie Lua-Skripte in Betracht ziehen. Skripte werden direkt auf dem Redis-Server ausgeführt, wodurch Netzwerklatenz reduziert und Atomarität sichergestellt wird. Lang laufende Lua-Skripte können Redis jedoch blockieren, daher müssen sie sorgfältig optimiert werden.

  4. Vermeiden Sie KEYS in der Produktion: Der Befehl KEYS ist O(N) (wobei N die Anzahl der Schlüssel in der Datenbank ist) und kann den Redis-Server für einen längeren Zeitraum blockieren, insbesondere bei großen Datenbanken. Verwenden Sie SCAN zum Iterieren über Schlüssel in Produktionsumgebungen. SCAN bietet eine iteratorähnliche Funktionalität, die pausiert und fortgesetzt werden kann, wodurch lange blockierende Operationen vermieden werden.

    # Schlecht in der Produktion
    redis-cli KEYS *
    
    # Gut in der Produktion für Iteration
    redis-cli SCAN 0 MATCH user:* COUNT 100
    
  5. Verbindungspooling: Stellen Sie sicher, dass Ihre Anwendung ein ordnungsgemäßes Verbindungspooling verwendet, um Verbindungen zu Redis effizient zu verwalten. Das Öffnen und Schließen von Verbindungen für jeden Befehl kann ressourcenintensiv sein.

  6. Sharding und Clustering: Wenn Ihr Datensatz oder Ihre Arbeitslast über das hinauswächst, was eine einzelne Redis-Instanz bewältigen kann, sollten Sie Ihre Daten auf mehrere Redis-Instanzen aufteilen (Sharding) oder Redis Cluster einführen. Dies verteilt die Last und die Daten und verhindert, dass eine einzelne Instanz zu einem Engpass wird.

  7. Lesereplikate: Für leseintensive Arbeitslasten lagern Sie Leseabfragen auf Redis-Lesereplikate aus. Dies skaliert den Lesedurchsatz und reduziert die Last auf der primären Instanz, sodass diese sich auf Schreibvorgänge konzentrieren kann.

Best Practices für die Verwendung von SLOWLOG

  • Regelmäßige Überwachung: Stellen Sie es nicht einfach ein und vergessen Sie es. Überprüfen Sie regelmäßig die SLOWLOG-Einträge, insbesondere nach Bereitstellungen oder während Spitzenlastzeiten.
  • Angemessene Schwellenwerte: Passen Sie slowlog-log-slower-than basierend auf der akzeptablen Latenz Ihrer Anwendung an. Was für eine App langsam ist, kann für eine andere normal sein.
  • Ausreichende Protokolllänge: Setzen Sie slowlog-max-len groß genug, um einen aussagekräftigen Verlauf zu behalten, aber nicht so groß, dass es übermäßig viel Speicher verbraucht.
  • Regelmäßig löschen: Verwenden Sie SLOWLOG RESET nach der Analyse von Einträgen, um frische Daten zu erhalten, oder erwägen Sie die Automatisierung dieses Prozesses, wenn Sie SLOWLOG in ein Überwachungssystem integrieren.
  • Client-Benennung: Verwenden Sie CLIENT SETNAME <name> in Ihrem Anwendungscode. Dies fügt SLOWLOG-Einträgen wertvollen Kontext hinzu und erleichtert die Rückverfolgung langsamer Befehle zu bestimmten Teilen Ihrer Anwendung.

Fazit

Verwenden Sie SLOWLOG, um teure Redis-Befehle zu erkennen, und beheben Sie dann das Zugriffsmuster, anstatt nur die Schwellenwerte zu erhöhen. Wenn der langsame Eintrag einen breiten Lesevorgang von einem riesigen Schlüssel zeigt, paginieren Sie das Ergebnis, scannen Sie inkrementell, ändern Sie das Datenmodell oder verlagern Sie die schwere Arbeit aus dem Anforderungspfad.