Warum verwendet Redis hohe CPU? Debugging- und Optimierungstechniken
Untersuchen Sie plötzliche hohe CPU-Auslastung in Redis, einem kritischen In-Memory-Datenspeicher. Diese Anleitung zeigt, wie Sie die Last mit den Befehlen `SLOWLOG` und `INFO` debuggen, um ineffiziente Operationen wie `KEYS *` oder das Löschen großer Schlüssel zu identifizieren. Lernen Sie praktische Optimierungstechniken, einschließlich der Umstellung auf asynchrones `UNLINK`, der Nutzung von Pipelining und der Anpassung von Persistenzeinstellungen, um die Serverlast sofort zu reduzieren und die optimale Redis-Leistung wiederherzustellen.
Warum verwendet Redis hohe CPU? Debugging- und Optimierungstechniken
Hohe Redis-CPU bedeutet normalerweise eines von drei Dingen: Redis führt zu viele Befehlsarbeiten auf seinem Hauptausführungspfad aus, Hintergrundarbeiten wie Persistenz erhöhen den Druck, oder Clients senden Datenverkehr in einer Form, die Redis nicht effizient verarbeiten kann. Die Lösung hängt davon ab, welcher Fall zutrifft.
Starten Sie Redis nicht neu, es sei denn, der Dienst fällt bereits aus. Ein Neustart kann das Symptom beseitigen und die Beweise löschen. Beginnen Sie damit, die Befehlsverzögerung, die Befehlsmischung, die Client-Anzahl, den Persistenzstatus und die Host-CPU zu erfassen. Diese Fakten zeigen Ihnen, ob Sie einen schlechten Befehl, ein schlechtes Verkehrsmuster, einen überlasteten einzelnen Kern oder einen lauten Host haben.
Verständnis der Redis-Architektur und CPU-Last
Redis wird oft als single-threaded beschrieben, was für die Befehlsausführung größtenteils zutrifft, aber modernes Redis kann auch Hintergrund-Threads und optionales I/O-Threading verwenden. Der praktische Punkt bleibt jedoch derselbe: Ein Befehl, der zu lange dauert, kann andere Clients verzögern, und ein gesättigter Kern kann ausreichen, um sichtbare Latenz zu erzeugen, selbst wenn die Maschine anderswo freie CPU hat.
Schlüsselfaktoren, die die Redis-CPU-Last beeinflussen
Häufige Ursachen sind teure Befehle, große Werte, Lua-Skripte, zu viele kleine Befehle, die einzeln in einer Round-Trip gesendet werden, starker Verbindungswechsel, Persistenzaktivitäten und Speicherdruck, der den Kernel härter arbeiten lässt, als Redis erwartet.
Debugging hoher CPU-Auslastung
Bevor Sie optimieren, müssen Sie die Ursache der Last genau identifizieren. Überwachungswerkzeuge und integrierte Redis-Befehle sind für die Diagnose unerlässlich.
1. Verwendung der Befehle INFO und LATENCY
Der Befehl INFO liefert eine Momentaufnahme des Serverstatus. Konzentrieren Sie sich auf den CPU-Abschnitt und die Befehlsstatistiken.
redis-cli INFO cpu
Achten Sie auf die Änderungsrate, nicht nur auf die absoluten Werte. Ein schnell steigender used_cpu_user deutet oft auf die Befehlsverarbeitung hin. Ein schnell steigender used_cpu_sys kann auf Kernel-Arbeit wie Netzwerk, Speicherverwaltung oder festplattenbezogene Aktivitäten hinweisen.
Die Latenzwerkzeuge zeigen Ereignisklassen, die Redis beobachtet hat:
redis-cli LATENCY LATEST
redis-cli LATENCY DOCTOR
2. Identifizierung langsamer Befehle mit SLOWLOG
Das Redis Slow Log zeichnet Befehle auf, die eine bestimmte Ausführungszeit überschreiten. Dies ist Ihr direktestes Werkzeug, um schlecht performende Operationen zu finden.
Das Redis Slow Log zeichnet Befehle auf, deren Ausführungszeit einen Schwellenwert überschreitet. Es enthält keine Netzwerkzeit oder Wartezeit im Client-Pool, daher wird es am besten zusammen mit Anwendungslatenzmetriken verwendet.
Beispielkonfiguration:
slowlog-log-slower-than 1000
slowlog-max-len 1024
Abrufen des Logs:
redis-cli SLOWLOG GET 10
Überprüfen Sie den Befehlsnamen, die Schlüsselnamen und die Dauer. Wenn KEYS, große HGETALL, riesige SMEMBERS, breite sortierte Set-Bereiche oder Lua-Skripte das Log dominieren, ist das CPU-Problem wahrscheinlich anwendungsgetrieben.
3. Überwachung der Netzwerk- und Client-Aktivität
MONITOR ist während eines Vorfalls verlockend, aber auf einem ausgelasteten Server teuer. Bevorzugen Sie INFO commandstats, INFO clients, Slow Log, Client-Bibliotheksmetriken und Stichproben von einem Replikat, falls vorhanden.
Nützliche Befehle:
redis-cli INFO commandstats
redis-cli INFO clients
redis-cli CLIENT LIST
Wenn sich das Befehlsvolumen nach einem Deployment verdoppelt hat, können Sie dies in cmdstat_get, cmdstat_hgetall oder ähnlichen Zählern sehen. Wenn Clients ständig verbinden und trennen, beheben Sie das Pooling, bevor Sie Redis optimieren.
Häufige Ursachen und Optimierungsstrategien
Sobald Sie problematische Befehle oder Prozesse identifiziert haben, wenden Sie gezielte Optimierungstechniken an.
1. Eliminierung blockierender Befehle
Die schnellsten Erfolge erzielen Sie normalerweise durch das Entfernen von Befehlen, die Redis zwingen, einen großen Schlüsselraum zu durchlaufen oder einen großen Wert zu serialisieren.
| Ineffizienter Befehl | Warum verursacht er hohe CPU | Optimierung / Alternative |
|---|---|---|
KEYS * |
Durchsucht den gesamten Schlüsselraum. O(N). | Verwenden Sie SCAN iterativ oder strukturieren Sie den Datenzugriff um. |
FLUSHALL / FLUSHDB |
Löscht jeden Schlüssel, es sei denn, der asynchrone Modus wird verwendet. | Verwenden Sie sorgfältig begrenztes Löschen, UNLINK oder asynchrones Flushen nur, wenn angemessen. |
HGETALL, SMEMBERS (bei sehr großen Sets) |
Ruft die gesamte Struktur in den Speicher und serialisiert sie. | Verwenden Sie HSCAN, SSCAN oder teilen Sie große Strukturen in kleinere Schlüssel auf. |
Verwenden Sie UNLINK anstelle von DEL für sehr große Schlüssel. DEL gibt Speicher synchron frei. UNLINK entfernt den Schlüssel aus dem Schlüsselraum und gibt Speicher asynchron frei, was normalerweise die sichtbare Latenz bei großen Löschvorgängen reduziert.
# Anstelle von DEL large_key
UNLINK large_key
2. Optimierung der Persistenz (RDB und AOF)
RDB-Snapshots und AOF-Rewrites verwenden Hintergrundprozesse und können dennoch den Elternprozess durch Fork-Kosten, Copy-on-Write-Speicher, Festplattenbandbreite und CPU-Konkurrenz beeinflussen.
- RDB-Snapshots: Wenn Sie häufig speichern (z. B. jede Minute), verursachen die wiederholten
fork()-Aufrufe wiederkehrende CPU-Spitzen. Reduzieren Sie die Häufigkeit automatischer Speicherungen. - AOF-Rewriting: AOF-Rewriting (
BGREWRITEAOF) ist ebenfalls ressourcenintensiv. Redis versucht, dies zu optimieren, indem es minimale I/O-Operationen durchführt, aber die CPU-Auslastung wird während des Prozesses steigen.
Wenn die Persistenz mit CPU-Spitzen zusammenfällt, überprüfen Sie INFO persistence und die Host-Festplattenmetriken. Sie können die RDB-Häufigkeit reduzieren, schwere Backups außerhalb von Verkehrsspitzen planen, mehr Speicherreserven lassen oder den Speicher verbessern. Das Anhalten der Persistenz kann die Last reduzieren, erhöht aber auch das Risiko von Datenverlust, daher sollte es eine bewusste betriebliche Entscheidung sein.
3. Umgang mit Speicherfragmentierung und Swapping
Während Speicherprobleme oft mit hohem Speicherverbrauch verbunden sind, können schwere Speicherfragmentierung oder, schlimmer noch, das Auslagern von Redis-Daten auf die Festplatte durch das Betriebssystem (Thrashing) die CPU-Auslastung drastisch erhöhen, da der Kernel um die Speicherverwaltung kämpft.
- Swapping überprüfen: Verwenden Sie Betriebssystemwerkzeuge (
vmstat,top), um zu überprüfen, ob das System aktiv Speicherseiten des Redis-Prozesses auslagert. - Speicherfragmentierungsverhältnis: Überprüfen Sie
mem_fragmentation_ratioinINFO memory. Ein hohes Verhältnis ist ein Hinweis darauf, dass das Allokatorverhalten Speicher verschwendet, aber bestätigen Sie dies mit RSS, Datensatzgröße und Host-Speichermetriken.
Wenn Swapping auftritt, reduzieren Sie den Datensatz, senken Sie maxmemory, verlagern Sie Arbeit vom Host oder fügen Sie Speicher hinzu. Redis ist nicht dafür ausgelegt, gut zu performen, wenn sein heißer Datensatz auf die Festplatte ausgelagert wird.
4. Netzwerkoptimierung und Pipelining
Wenn die CPU-Last mit einer hohen Anzahl kleiner Befehle korreliert, liegt das Problem möglicherweise am Befehls-Overhead und Netzwerkwechsel, nicht an einem offensichtlich langsamen Befehl.
Pipelining ermöglicht es einem Client, mehrere Befehle zu senden, ohne nach jedem auf eine Antwort zu warten. Es reduziert Round-Trips und kann den Durchsatz für Bulk-Schreib- oder Lesevorgänge verbessern. Halten Sie Pipeline-Batches begrenzt; eine Pipeline mit Tausenden schweren Befehlen kann ihre eigene Latenzspitze erzeugen.
Best Practices für nachhaltige Leistung
Um zukünftige CPU-Spitzen zu vermeiden, übernehmen Sie diese architektonischen und konfigurativen Best Practices:
- Verwenden Sie
UNLINKfür Schlüssel, die groß sein könnten. - Ersetzen Sie
KEYSdurchSCANund ersetzen Sie vollständige Sammlungslesevorgänge durch cursor-basierte Lesevorgänge. - Verfolgen Sie
INFO commandstatsnach Deployments, damit Sie nicht von einem neuen Befehlsmuster überrascht werden. - Passen Sie die Persistenz unter Berücksichtigung des tatsächlichen Festplatten- und Speicherspielraums an.
- Wenn eine Redis-Instanz nach Befehlsbehebungen legitim gesättigt ist, teilen Sie die Arbeitslast mit Redis Cluster, clientseitigem Sharding, separaten Cache/Sitzungsinstanzen oder einer größeren Instanz mit besserer Single-Core-Leistung.
Eine schnelle Incident-Checkliste
Während einer Spitze führen Sie aus:
redis-cli INFO cpu
redis-cli INFO commandstats
redis-cli INFO clients
redis-cli INFO memory
redis-cli INFO persistence
redis-cli SLOWLOG GET 20
redis-cli LATENCY LATEST
Setzen Sie diese Ergebnisse dann mit Anwendungsdeployments, Cron-Jobs, Verkehrsänderungen, Persistenzergebnissen und Host-Metriken in Beziehung. Hohe Redis-CPU ist normalerweise behebbar, aber die Lösung ist spezifisch: Entfernen Sie den teuren Befehl, bündeln Sie den gesprächigen Client, stoppen Sie den Verbindungswechsel, geben Sie der Persistenz Raum zum Arbeiten, oder teilen Sie die Arbeitslast, wenn eine einzelne Instanz wirklich an ihrer Grenze ist.