Risoluzione Efficace degli Errori Comuni di Connessione a Redis

Hai problemi di connessione a Redis? Questa guida pratica fornisce passaggi chiari per diagnosticare e risolvere errori comuni come 'Connection Refused', 'Timeouts' e 'Authentication Failures'. Impara a verificare lo stato del server, le configurazioni di rete, i firewall e le metriche delle prestazioni di Redis. Include esempi pratici per `redis-cli` e librerie client per ripristinare rapidamente le tue connessioni Redis.

Risoluzione Efficace degli Errori Comuni di Connessione a Redis

Gli errori di connessione a Redis sono generalmente semplici una volta che li suddividi in tre domande: il client può raggiungere host e porta, Redis accetta la connessione e il client è autorizzato a eseguire comandi dopo la connessione?

Procedi in questo ordine. Saltare direttamente al codice dell'applicazione spreca tempo quando Redis è fermo. Ricostruire una regola del firewall spreca tempo quando la password è sbagliata. Una piccola checklist ripetibile ti porta più velocemente al vero guasto.

Prima, testa dallo stesso posto dell'applicazione

Testare dal tuo laptop è utile, ma non prova che un pod Kubernetes, una VM, un contenitore o un runner CI possano raggiungere Redis. Inizia all'interno della stessa posizione di rete dell'applicazione che presenta il problema.

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

Output previsto:

PONG

Se Redis richiede TLS, usa le opzioni TLS previste dal tuo deployment:

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

Se Redis richiede autenticazione:

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

Fai attenzione alle password nella cronologia della shell. Per la produzione, usa credenziali temporanee o variabili d'ambiente quando possibile.

Connessione rifiutata

ECONNREFUSED, Connection refused o Could not connect to Redis di solito significa che la connessione TCP ha raggiunto l'host di destinazione, ma nulla l'ha accettata su quella porta. Le cause più comuni sono semplici:

  • Redis non è in esecuzione.
  • Il client sta usando host o porta sbagliati.
  • Redis è vincolato solo a localhost.
  • Un contenitore o un mapping del servizio punta alla porta sbagliata.
  • Un firewall rifiuta attivamente la connessione.

Sull'host Redis, controlla il processo e il listener:

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

Vuoi vedere Redis in ascolto sull'indirizzo e porta previsti, comunemente 127.0.0.1:6379, 0.0.0.0:6379 o un indirizzo di interfaccia privata.

Controlla redis.conf o la configurazione effettiva:

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

Se bind è 127.0.0.1, i client remoti non possono connettersi direttamente. Questo è spesso intenzionale. Non cambiarlo in 0.0.0.0 come soluzione rapida a meno che Redis non sia protetto da autenticazione, ACL, regole del firewall e rete privata. Redis esposto su internet pubblico è un grave incidente di sicurezza in attesa di accadere.

In Docker, ricorda la differenza tra porta del contenitore e porta dell'host:

docker ps
docker port <redis-container>

All'interno di una rete Docker Compose, le applicazioni di solito si connettono al nome del servizio e alla porta interna:

redis://redis:6379

Dall'host, possono connettersi a una porta pubblicata come localhost:6379 o localhost:6381, a seconda del mapping.

Timeout di connessione

Un timeout significa che il client ha aspettato e non ha completato l'operazione in tempo. A differenza delle connessioni rifiutate, i timeout spesso indicano un problema di percorso o un server occupato.

Controlla il percorso TCP:

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

ping non è perfetto perché ICMP potrebbe essere bloccato mentre TCP funziona, ma può rivelare errori evidenti di DNS o routing. nc è più vicino a ciò di cui il client Redis ha bisogno.

Se TCP si connette ma i comandi Redis vanno in timeout, controlla se Redis è occupato:

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

Cerca client bloccati, conteggi elevati di client connessi, memoria vicina a maxmemory, swap sull'host, comandi lenti ed eventi di latenza. Un singolo comando costoso come KEYS *, un grande HGETALL o uno script Lua lungo possono ritardare client non correlati perché l'esecuzione dei comandi Redis è in gran parte single-threaded.

Controlla anche le impostazioni di timeout del client. Alcune librerie usano default brevi per i timeout di connessione o di comando. Aumentare il timeout può ridurre falsi fallimenti su una rete lenta, ma non dovrebbe nascondere un'istanza Redis sovraccarica. Se un semplice PING richiede secondi dall'host dell'applicazione, risolvi quello prima di ottimizzare i tentativi.

Problemi di risoluzione dei nomi e di endpoint sbagliati

Non tutti gli errori di connessione sono Redis. DNS e service discovery ne causano molti.

Dall'host dell'applicazione:

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

Controlla se l'applicazione sta usando un endpoint di replica di sola lettura, un endpoint sentinel, un endpoint cluster o un endpoint nodo diretto. I client Redis Cluster necessitano di librerie cluster-aware perché le chiavi possono appartenere a slot diversi e i comandi possono ricevere reindirizzamenti. Un client non cluster-aware può connettersi con successo e poi fallire con errori MOVED o ASK una volta che invia comandi reali.

Errori di autenticazione

I fallimenti di autenticazione si presentano come:

  • NOAUTH Authentication required
  • WRONGPASS invalid username-password pair
  • NOPERM this user has no permissions
  • Eccezioni di autenticazione specifiche della libreria client

Per Redis 6 e versioni successive, gli utenti ACL sono comuni. Una stringa di connessione può aver bisogno sia di nome utente che di password:

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

Con l'utente predefinito, alcuni client usano solo una password:

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

Controlla la configurazione dell'utente attivo se hai accesso amministrativo:

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

NOAUTH significa che il client non si è autenticato prima di emettere un comando. WRONGPASS significa che l'autenticazione è stata tentata ma rifiutata. NOPERM significa che l'autenticazione ha funzionato, ma l'utente non ha il permesso per il comando, il pattern di chiave o il canale Pub/Sub.

Quando i segreti ruotano, conferma che ogni processo in esecuzione abbia effettivamente ricevuto il nuovo valore. Nelle piattaforme container, aggiornare un oggetto segreto non sempre riavvia i pod o i processi esistenti. Un fallimento comune nel mondo reale è metà dell'applicazione che usa la nuova password e metà che usa ancora quella vecchia.

Disallineamento TLS

Gli errori TLS possono sembrare reset di connessione, timeout o errori di protocollo illeggibili.

Controlla la porta. I servizi gestiti spesso usano porte diverse per TLS e Redis non TLS. Ad esempio, un endpoint può aspettarsi il protocollo Redis semplice e un altro può aspettarsi TLS dal primo byte.

Testa con:

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

Se la tua organizzazione usa certificati privati, il client potrebbe anche aver bisogno di un file CA:

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

Nei log dell'applicazione, gli errori di certificato sono spesso più chiari dell'eccezione Redis di alto livello. Cerca messaggi su autorità sconosciute, certificati scaduti, disallineamento del nome host o fallimento dell'handshake.

Troppe connessioni

Redis ha un limite maxclients. Anche il sistema operativo ha limiti di descrittori di file. Quando uno dei due è esaurito, nuovi client possono fallire o i client esistenti possono comportarsi male.

Controlla:

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

Campi utili includono connected_clients, blocked_clients e rejected_connections da INFO stats.

Troppe connessioni di solito derivano da uno di questi pattern:

  • Creare un nuovo client Redis per ogni richiesta web.
  • Non chiudere i client in job di breve durata.
  • Troppi processi worker, ciascuno con il proprio grande pool.
  • Sottoscrizioni Pub/Sub che prendono in prestito connessioni da un pool di comandi normale.
  • Tempeste di tentativi durante un riavvio di Redis.

Risolvi la forma dell'applicazione prima di aumentare i limiti. Usa un client condiviso o un pool limitato per processo. Aggiungi backoff con jitter per la riconnessione in modo che ogni istanza non si riconnetta allo stesso millisecondo dopo un'interruzione.

Modalità protetta e impostazioni di bind

La modalità protetta di Redis è progettata per ridurre i danni da esposizione accidentale. Se Redis è vincolato ampiamente e non ha autenticazione, la modalità protetta può rifiutare connessioni remote.

Controlla:

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

Non disabilitare la modalità protetta solo per far funzionare una connessione remota. Il percorso più sicuro è di solito rete privata più autenticazione e un indirizzo bind ristretto. Se Redis deve accettare client remoti, mettilo su una subnet privata, limita gli IP di origine, richiedi credenziali e usa TLS dove appropriato.

Un ordine pratico delle operazioni

Quando un'applicazione non riesce a connettersi, usa questa sequenza:

  1. Dall'ambiente dell'applicazione, esegui redis-cli PING contro lo stesso host e porta.
  2. Se rifiutato, controlla il processo Redis, il listener, il bind, la porta e il mapping del contenitore.
  3. Se timeout, controlla routing, regole del firewall, carico del server, comandi lenti e impostazioni di timeout del client.
  4. Se l'autenticazione fallisce, verifica nome utente, password, permessi ACL e distribuzione del segreto.
  5. Se solo alcuni comandi falliscono, controlla i permessi ACL comando/chiave e i reindirizzamenti Redis Cluster.
  6. Se i fallimenti avvengono sotto carico, controlla i conteggi delle connessioni, le dimensioni del pool, i tentativi e le metriche delle risorse del server.

La risoluzione dei problemi di connessione è principalmente raccolta di prove. Ottieni un risultato CLI pulito dallo stesso posto dell'app, poi confrontalo con ciò che sta facendo la libreria client. Una volta che questi due percorsi differiscono, il divario è solitamente visibile: un flag TLS mancante, una password vecchia, un nome di servizio sbagliato o un pool che crea molte più connessioni di quelle per cui Redis è stato dimensionato.

Leggere gli errori dell'applicazione senza reagire in modo eccessivo

Le librerie client avvolgono gli errori Redis nel loro linguaggio. Un servizio Node.js può mostrare ECONNRESET, un worker Python può mostrare redis.exceptions.ConnectionError e un servizio Java può segnalare un timeout di acquisizione del pool. Questi possono tutti descrivere diversi livelli dello stesso problema.

Separa:

  • Timeout di connessione: la connessione TCP non si è completata abbastanza velocemente.
  • Timeout di lettura: la connessione esiste, ma una risposta al comando non è arrivata in tempo.
  • Reset di connessione: la connessione è stata chiusa da Redis, un proxy, la rete o il peer.
  • Timeout del pool: l'applicazione non ha potuto prendere in prestito una connessione Redis dal proprio pool.
  • Errore di autenticazione: Redis ha rifiutato le credenziali o i permessi.

Un timeout del pool è facile da interpretare erroneamente come un'interruzione di Redis. A volte Redis funziona bene, ma l'applicazione ha preso in prestito tutte le connessioni del pool e non le ha mai restituite. L'uso improprio di Pub/Sub può causare questo. Così come comandi bloccanti lunghi, gestori di richieste che dimenticano di chiudere i client o un pool troppo piccolo per la concorrenza del processo.

Controlla entrambi i lati contemporaneamente. Nell'applicazione, ispeziona le metriche del pool se la libreria le espone: connessioni attive, connessioni inattive, in attesa, conteggio tentativi. In Redis, controlla:

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

Se Redis mostra solo una manciata di client ma l'applicazione dice che il suo pool è esaurito, il problema è probabilmente all'interno del processo dell'applicazione. Se Redis mostra migliaia di connessioni dallo stesso deployment, il servizio potrebbe creare client troppo spesso.

I tentativi meritano attenzione speciale. Un ciclo di riconnessione senza backoff può trasformare un breve riavvio di Redis in una tempesta. Ogni istanza dell'applicazione tenta di riconnettersi immediatamente, l'autenticazione e gli handshake TLS aumentano, e Redis deve riprendersi mentre viene martellato dai client. Usa backoff esponenziale con jitter. Decidi anche quali comandi sono sicuri da ritentare. Ritentare un GET di cache idempotente è diverso dal ritentare una scrittura che potrebbe già essere riuscita prima che la connessione cadesse.

Per le note sugli incidenti, cattura il testo esatto dell'errore e la tempistica. "Redis era giù" è spesso sbagliato. "Dalle 14:03 alle 14:06 UTC, i pod dell'app hanno visto read timeout mentre la CPU di Redis era a un core e SLOWLOG mostrava grandi chiamate HGETALL" è attuabile.