Fehlerbehebung bei häufigen Redis-Verbindungsfehlern

Haben Sie Probleme mit Redis-Verbindungen? Dieser praktische Leitfaden bietet klare Schritte zur Diagnose und Behebung häufiger Fehler wie 'Verbindung abgelehnt', 'Zeitüberschreitungen' und 'Authentifizierungsfehler'. Erfahren Sie, wie Sie Serverstatus, Netzwerkkonfigurationen, Firewalls und Redis-Leistungsmetriken überprüfen. Enthält umsetzbare Beispiele für `redis-cli` und Client-Bibliotheken, um Ihre Redis-Verbindungen effizient wiederherzustellen.

Fehlerbehebung bei häufigen Redis-Verbindungsfehlern

Redis-Verbindungsfehler sind in der Regel einfach, sobald Sie sie in drei Fragen unterteilen: Kann der Client den Host und Port erreichen, akzeptiert Redis die Verbindung und darf der Client nach dem Verbinden Befehle ausführen?

Gehen Sie in dieser Reihenfolge vor. Direkt in den Anwendungscode zu springen, verschwendet Zeit, wenn Redis gestoppt ist. Eine Firewall-Regel neu zu erstellen, verschwendet Zeit, wenn das Passwort falsch ist. Eine kleine, wiederholbare Checkliste führt Sie schneller zum eigentlichen Fehler.

Zuerst vom gleichen Ort wie die Anwendung testen

Das Testen von Ihrem Laptop aus ist nützlich, beweist aber nicht, dass ein Kubernetes-Pod, eine VM, ein Container oder ein CI-Runner Redis erreichen kann. Beginnen Sie innerhalb des gleichen Netzwerkstandorts wie die fehlschlagende Anwendung.

redis-cli -h redis.example.internal -p 6379 PING

Erwartete Ausgabe:

PONG

Wenn Redis TLS erfordert, verwenden Sie die von Ihrer Bereitstellung erwarteten TLS-Optionen:

redis-cli --tls -h redis.example.internal -p 6380 PING

Wenn Redis Authentifizierung erfordert:

redis-cli -u redis://app-user:[email protected]:6379 PING

Seien Sie vorsichtig mit Passwörtern im Shell-Verlauf. Verwenden Sie für die Produktion nach Möglichkeit temporäre Anmeldeinformationen oder Umgebungsvariablen.

Verbindung abgelehnt

ECONNREFUSED, Connection refused oder Could not connect to Redis bedeutet normalerweise, dass die TCP-Verbindung den Zielhost erreicht hat, aber nichts auf diesem Port akzeptiert hat. Die häufigsten Ursachen sind einfach:

  • Redis läuft nicht.
  • Der Client verwendet den falschen Host oder Port.
  • Redis ist nur an localhost gebunden.
  • Ein Container- oder Dienst-Mapping zeigt auf den falschen Port.
  • Eine Firewall lehnt die Verbindung aktiv ab.

Überprüfen Sie auf dem Redis-Host den Prozess und den Listener:

redis-cli PING
ps aux | grep '[r]edis-server'
ss -ltnp | grep redis

Sie möchten sehen, dass Redis auf der erwarteten Adresse und dem erwarteten Port lauscht, üblicherweise 127.0.0.1:6379, 0.0.0.0:6379 oder einer privaten Schnittstellenadresse.

Überprüfen Sie redis.conf oder die effektive Konfiguration:

redis-cli CONFIG GET bind
redis-cli CONFIG GET port
redis-cli CONFIG GET protected-mode

Wenn bind auf 127.0.0.1 gesetzt ist, können entfernte Clients keine direkte Verbindung herstellen. Das ist oft beabsichtigt. Ändern Sie es nicht als schnelle Lösung auf 0.0.0.0, es sei denn, Redis ist durch Authentifizierung, ACLs, Firewall-Regeln und private Netzwerke geschützt. Redis, das im öffentlichen Internet freigegeben ist, ist ein schwerwiegender Sicherheitsvorfall, der nur darauf wartet, zu passieren.

Denken Sie in Docker an den Unterschied zwischen Container-Port und Host-Port:

docker ps
docker port <redis-container>

Innerhalb eines Docker-Compose-Netzwerks verbinden sich Anwendungen normalerweise mit dem Dienstnamen und dem internen Port:

redis://redis:6379

Vom Host aus können sie sich je nach Mapping mit einem veröffentlichten Port wie localhost:6379 oder localhost:6381 verbinden.

Verbindungszeitüberschreitung

Eine Zeitüberschreitung bedeutet, dass der Client gewartet hat und den Vorgang nicht rechtzeitig abgeschlossen hat. Im Gegensatz zu abgelehnten Verbindungen deuten Zeitüberschreitungen oft auf ein Pfadproblem oder einen ausgelasteten Server hin.

Überprüfen Sie den TCP-Pfad:

nc -vz redis.example.internal 6379
ping -c 5 redis.example.internal

ping ist nicht perfekt, da ICMP blockiert sein kann, während TCP funktioniert, aber es kann offensichtliche DNS- oder Routing-Fehler aufdecken. nc kommt dem näher, was der Redis-Client benötigt.

Wenn TCP verbindet, aber Redis-Befehle eine Zeitüberschreitung aufweisen, überprüfen Sie, ob Redis ausgelastet ist:

redis-cli INFO clients
redis-cli INFO stats
redis-cli INFO memory
redis-cli SLOWLOG GET 10
redis-cli LATENCY DOCTOR

Achten Sie auf blockierte Clients, hohe Anzahl verbundener Clients, Speicher nahe maxmemory, Swap auf dem Host, langsame Befehle und Latenzereignisse. Ein einzelner teurer Befehl wie KEYS *, ein großes HGETALL oder ein langes Lua-Skript kann nicht verwandte Clients verzögern, da die Redis-Befehlsausführung weitgehend single-threaded ist.

Überprüfen Sie auch die Client-Timeout-Einstellungen. Einige Bibliotheken verwenden kurze Standardwerte für Verbindungs- oder Befehls-Timeouts. Eine Erhöhung des Timeouts kann falsche Fehler in einem langsamen Netzwerk reduzieren, sollte aber eine überlastete Redis-Instanz nicht verbergen. Wenn ein einfaches PING vom Anwendungshost Sekunden dauert, beheben Sie das zuerst, bevor Sie Wiederholungen optimieren.

Namensauflösung und Probleme mit falschen Endpunkten

Nicht jeder Verbindungsfehler ist Redis. DNS und Service Discovery verursachen viele davon.

Vom Anwendungshost aus:

getent hosts redis.example.internal
nslookup redis.example.internal

In Kubernetes:

kubectl exec -it deploy/my-app -- sh
getent hosts redis.default.svc.cluster.local
nc -vz redis.default.svc.cluster.local 6379

Überprüfen Sie, ob die Anwendung einen Read-Replica-Endpunkt, einen Sentinel-Endpunkt, einen Cluster-Endpunkt oder einen direkten Knoten-Endpunkt verwendet. Redis-Cluster-Clients benötigen cluster-fähige Bibliotheken, da Schlüssel zu verschiedenen Slots gehören können und Befehle Weiterleitungen erhalten können. Ein nicht cluster-fähiger Client kann sich erfolgreich verbinden und dann mit MOVED- oder ASK-Fehlern fehlschlagen, sobald er echte Befehle sendet.

Authentifizierungsfehler

Authentifizierungsfehler zeigen sich als:

  • NOAUTH Authentication required
  • WRONGPASS invalid username-password pair
  • NOPERM this user has no permissions
  • Client-Bibliothek-spezifische Authentifizierungsausnahmen

Für Redis 6 und neuer sind ACL-Benutzer üblich. Ein Verbindungsstring benötigt möglicherweise sowohl Benutzername als auch Passwort:

redis://app-user:[email protected]:6379/0

Mit dem Standardbenutzer verwenden einige Clients nur ein Passwort:

redis://:[email protected]:6379/0

Überprüfen Sie die aktive Benutzerkonfiguration, wenn Sie Admin-Zugriff haben:

redis-cli ACL LIST
redis-cli ACL GETUSER app-user

NOAUTH bedeutet, dass der Client sich nicht authentifiziert hat, bevor er einen Befehl ausgeführt hat. WRONGPASS bedeutet, dass die Authentifizierung versucht, aber abgelehnt wurde. NOPERM bedeutet, dass die Authentifizierung funktioniert hat, der Benutzer jedoch keine Berechtigung für den Befehl, das Schlüsselmuster oder den Pub/Sub-Kanal hat.

Wenn Geheimnisse rotiert werden, bestätigen Sie, dass jeder laufende Prozess tatsächlich den neuen Wert erhalten hat. In Container-Plattformen aktualisiert das Aktualisieren eines Secret-Objekts nicht immer vorhandene Pods oder Prozesse. Ein häufiger realer Fehler ist, dass die Hälfte der Anwendung das neue Passwort und die Hälfte noch das alte verwendet.

TLS-Konfigurationsfehler

TLS-Fehler können wie Verbindungsabbrüche, Zeitüberschreitungen oder unlesbare Protokollfehler aussehen.

Überprüfen Sie den Port. Verwaltete Dienste verwenden oft unterschiedliche Ports für TLS- und Nicht-TLS-Redis. Beispielsweise kann ein Endpunkt das einfache Redis-Protokoll erwarten und ein anderer TLS ab dem ersten Byte.

Testen Sie mit:

redis-cli --tls -h redis.example.internal -p 6380 PING
redis-cli -h redis.example.internal -p 6379 PING

Wenn Ihre Organisation private Zertifikate verwendet, benötigt der Client möglicherweise auch eine CA-Datei:

redis-cli --tls --cacert /path/to/ca.pem -h redis.example.internal -p 6380 PING

In Anwendungsprotokollen sind Zertifikatsfehler oft klarer als die übergeordnete Redis-Ausnahme. Achten Sie auf Meldungen über unbekannte Zertifizierungsstellen, abgelaufene Zertifikate, Hostnamen-Konflikte oder Handshake-Fehler.

Zu viele Verbindungen

Redis hat ein maxclients-Limit. Das Betriebssystem hat auch Dateideskriptor-Limits. Wenn eines davon erschöpft ist, können neue Clients fehlschlagen oder vorhandene Clients sich schlecht verhalten.

Überprüfen Sie:

redis-cli INFO clients
redis-cli CONFIG GET maxclients
ulimit -n

Nützliche Felder sind connected_clients, blocked_clients und rejected_connections aus INFO stats.

Zu viele Verbindungen resultieren normalerweise aus einem dieser Muster:

  • Erstellen eines neuen Redis-Clients pro Webanfrage.
  • Nicht schließen von Clients in kurzlebigen Jobs.
  • Zu viele Worker-Prozesse, jeder mit einem eigenen großen Pool.
  • Pub/Sub-Abonnements, die Verbindungen aus einem normalen Befehlspool ausleihen.
  • Wiederholungsstürme während eines Redis-Neustarts.

Beheben Sie die Anwendungsform, bevor Sie die Limits erhöhen. Verwenden Sie einen gemeinsamen Client oder einen begrenzten Pool pro Prozess. Fügen Sie einen verrauschten Wiederholungs-Backoff hinzu, damit nicht jede Instanz nach einem Ausfall zur gleichen Millisekunde erneut verbindet.

Geschützter Modus und Bind-Einstellungen

Der geschützte Modus von Redis soll die Schäden durch versehentliche Offenlegung reduzieren. Wenn Redis breit gebunden ist und keine Authentifizierung hat, kann der geschützte Modus entfernte Verbindungen ablehnen.

Überprüfen Sie:

redis-cli CONFIG GET protected-mode
redis-cli CONFIG GET bind
redis-cli CONFIG GET requirepass

Deaktivieren Sie den geschützten Modus nicht nur, um eine entfernte Verbindung zum Laufen zu bringen. Der sicherere Weg ist normalerweise privates Netzwerk plus Authentifizierung und eine enge Bind-Adresse. Wenn Redis entfernte Clients akzeptieren muss, setzen Sie es in ein privates Subnetz, schränken Sie Quell-IPs ein, fordern Sie Anmeldeinformationen und verwenden Sie gegebenenfalls TLS.

Eine praktische Reihenfolge der Operationen

Wenn eine Anwendung keine Verbindung herstellen kann, verwenden Sie diese Sequenz:

  1. Führen Sie von der Anwendungsumgebung aus redis-cli PING gegen denselben Host und Port aus.
  2. Bei Ablehnung überprüfen Sie Redis-Prozess, Listener, Bind, Port und Container-Mapping.
  3. Bei Zeitüberschreitung überprüfen Sie Routing, Firewall-Regeln, Serverlast, langsame Befehle und Client-Timeout-Einstellungen.
  4. Bei Authentifizierungsfehlern überprüfen Sie Benutzername, Passwort, ACL-Berechtigungen und Secret-Rollout.
  5. Wenn nur einige Befehle fehlschlagen, überprüfen Sie ACL-Befehls-/Schlüsselberechtigungen und Redis-Cluster-Weiterleitungen.
  6. Wenn Fehler unter Last auftreten, überprüfen Sie Verbindungszahlen, Pool-Größen, Wiederholungen und Server-Ressourcenmetriken.

Die Fehlerbehebung bei Verbindungen besteht hauptsächlich aus dem Sammeln von Beweisen. Holen Sie sich ein sauberes CLI-Ergebnis vom gleichen Ort wie die App und vergleichen Sie es dann mit dem, was die Client-Bibliothek tut. Sobald sich diese beiden Pfade unterscheiden, ist die Lücke normalerweise sichtbar: ein fehlendes TLS-Flag, ein altes Passwort, ein falscher Dienstname oder ein Pool, der weit mehr Verbindungen erstellt, als Redis ausgelegt ist.

Anwendungsfehler lesen, ohne zu überreagieren

Client-Bibliotheken verpacken Redis-Fehler in ihrer eigenen Sprache. Ein Node.js-Dienst kann ECONNRESET anzeigen, ein Python-Worker kann redis.exceptions.ConnectionError anzeigen und ein Java-Dienst kann eine Pool-Akquisitions-Zeitüberschreitung melden. Diese können alle verschiedene Ebenen desselben Problems beschreiben.

Trennen Sie sie:

  • Verbindungs-Timeout: Die TCP-Verbindung wurde nicht schnell genug hergestellt.
  • Lese-Timeout: Die Verbindung besteht, aber eine Befehlsantwort kam nicht rechtzeitig an.
  • Verbindungsabbruch: Die Verbindung wurde von Redis, einem Proxy, dem Netzwerk oder dem Peer geschlossen.
  • Pool-Timeout: Die Anwendung konnte keine Redis-Verbindung aus ihrem eigenen Pool ausleihen.
  • Authentifizierungsfehler: Redis hat die Anmeldeinformationen oder Berechtigungen abgelehnt.

Ein Pool-Timeout kann leicht als Redis-Ausfall fehlinterpretiert werden. Manchmal ist Redis in Ordnung, aber die Anwendung hat jede Pool-Verbindung ausgeliehen und nie zurückgegeben. Pub/Sub-Missbrauch kann dies verursachen. Auch lange blockierende Befehle, Request-Handler, die vergessen, Clients zu schließen, oder ein Pool, der für die Parallelität des Prozesses zu klein ist.

Überprüfen Sie beide Seiten gleichzeitig. Untersuchen Sie in der Anwendung die Pool-Metriken, wenn die Bibliothek sie bereitstellt: aktive Verbindungen, Leerlaufverbindungen, Wartende, Wiederholungsanzahl. Überprüfen Sie in Redis:

redis-cli INFO clients
redis-cli CLIENT LIST | head

Wenn Redis nur eine Handvoll Clients anzeigt, die Anwendung aber sagt, ihr Pool sei erschöpft, liegt das Problem wahrscheinlich im Anwendungsprozess. Wenn Redis Tausende von Verbindungen von derselben Bereitstellung anzeigt, erstellt der Dienst möglicherweise zu oft Clients.

Wiederholungen verdienen besondere Aufmerksamkeit. Eine Wiederholungsschleife ohne Backoff kann einen kurzen Redis-Neustart in einen Sturm verwandeln. Jede Anwendungsinstanz versucht sofort, sich erneut zu verbinden, Authentifizierungs- und TLS-Handshakes steigen an, und Redis muss sich erholen, während es von Clients bombardiert wird. Verwenden Sie exponentiellen Backoff mit Jitter. Entscheiden Sie auch, welche Befehle sicher wiederholt werden können. Das Wiederholen eines idempotenten Cache-GET unterscheidet sich vom Wiederholen eines Schreibvorgangs, der möglicherweise bereits erfolgreich war, bevor die Verbindung abbrach.

Für Vorfallnotizen erfassen Sie den genauen Fehlertext und das Timing. "Redis war ausgefallen" ist oft falsch. "Von 14:03 bis 14:06 UTC sahen App-Pods Lese-Timeouts, während Redis-CPU bei einem Kern lag und SLOWLOG große HGETALL-Aufrufe zeigte" ist umsetzbar.