Quando Dovresti Usare Redis come Message Broker?

Scopri gli scenari ideali per sfruttare Redis come message broker utilizzando le sue due funzionalità principali: Pub/Sub e Streams. Questa guida completa illustra i vantaggi in termini di prestazioni, la bassa latenza e i benefici infrastrutturali della messaggistica Redis. Impara le differenze cruciali tra Pub/Sub effimero e Streams durevoli, comprendi i loro limiti rispetto a broker dedicati come Kafka e trova casi d'uso pratici—dalla semplice invalidazione della cache a code di task leggere e robuste—per aiutarti a scegliere lo strumento giusto per le tue esigenze di comunicazione asincrona.

Quando Dovresti Usare Redis come Message Broker?

Redis può essere un buon message broker quando il compito è piccolo, veloce e vicino ai dati che già conservi in Redis. Può anche essere lo strumento sbagliato se hai bisogno di forti garanzie di consegna, conservazione a lungo termine, funzionalità di routing o un broker che continui a funzionare comodamente quando la cronologia dei messaggi è molto più grande della memoria.

La decisione diventa più semplice se smetti di chiederti "Redis può fare messaggistica?" e ti chiedi "Quale primitiva di messaggistica di Redis corrisponde al tipo di fallimento che posso tollerare?"

Redis ti offre diversi pattern, ma due sono i più importanti per questa domanda:

  • Pub/Sub per trasmissioni in diretta.
  • Streams per l'elaborazione di messaggi durevole, simile a un log, con gruppi di consumatori.

Sembrano simili da lontano. Non lo sono operativamente.

Usa Pub/Sub quando perdere un messaggio è accettabile

Redis Pub/Sub è una trasmissione in diretta. Un publisher invia a un canale. I subscriber connessi ricevono il messaggio. Redis non memorizza quel messaggio per i subscriber disconnessi e non esiste un riconoscimento integrato.

Questo è perfetto per alcuni lavori:

SUBSCRIBE cache:invalidations
PUBLISH cache:invalidations 'product:123'

Se un'istanza dell'applicazione perde quell'invalidazione perché è ripartita nel momento sbagliato, il mondo non dovrebbe finire. La cache locale dovrebbe avere TTL, controlli di versione o un altro modo per recuperare. Pub/Sub è un percorso di notifica, non la fonte di verità.

Buoni casi d'uso per Pub/Sub:

  • Invalidazione della cache tra istanze dell'applicazione.
  • Aggiornamenti UI in tempo reale dove i client si preoccupano solo dello stato corrente.
  • Segnali di presenza come "l'utente sta scrivendo" o "il battito cardiaco del worker è cambiato".
  • Notifiche leggere di distribuzione o modifica della configurazione.
  • Eventi fan-out dove i messaggi persi sono tollerabili.

Cattivi casi d'uso per Pub/Sub:

  • Elaborazione dei pagamenti.
  • Lavori email che devono essere inviati eventualmente.
  • Aggiornamenti dell'inventario che non devono essere saltati.
  • Log di audit.
  • Qualsiasi cosa in cui un consumatore disconnesso deve recuperare in seguito.

Pub/Sub è veloce perché fa meno cose. Questo è il compromesso.

Usa Streams quando i consumatori devono recuperare

Redis Streams memorizza le voci in una struttura dati di stream:

XADD orders:events * order_id 42 status paid

I consumatori possono leggere da una posizione:

XREAD COUNT 10 STREAMS orders:events 0

I gruppi di consumatori permettono a più worker di condividere il lavoro:

XGROUP CREATE orders:events order-workers 0 MKSTREAM
XREADGROUP GROUP order-workers worker-1 COUNT 10 STREAMS orders:events >
XACK orders:events order-workers 1740000000000-0

Con i gruppi di consumatori, un messaggio consegnato a un worker rimane nell'elenco delle voci in sospeso fino a quando non viene riconosciuto con XACK. Se un worker muore dopo aver letto ma prima di riconoscere, un altro worker può ispezionare e rivendicare il lavoro in sospeso. Questo ti dà un'elaborazione at-least-once quando costruisci il consumatore correttamente.

At-least-once significa che i duplicati sono possibili. Il tuo worker deve essere idempotente. Ad esempio, un worker email dovrebbe registrare che email_job_id=abc123 è stato inviato prima di tentare di inviarlo di nuovo. Un worker degli ordini dovrebbe evitare di addebitare due volte se vede la stessa voce dello stream due volte.

Buoni casi d'uso per Streams:

  • Lavori in background leggeri.
  • Eventi di servizio interni che necessitano di replay dopo brevi interruzioni.
  • Log di eventi di piccole e medie dimensioni.
  • Pool di worker dove ogni lavoro dovrebbe essere elaborato da un worker in un gruppo.
  • Feed di attività o log di cambiamenti di stato con conservazione limitata.

Gli Streams non sono gratuiti. Le voci vivono nella memoria di Redis a meno che non vengano troncate o scadute dal tuo design. Se non tronchi mai uno stream attivo, lo stream diventa il tuo prossimo incidente di memoria.

Usa il troncamento:

XADD orders:events MAXLEN ~ 100000 * order_id 42 status paid
XTRIM orders:events MAXLEN ~ 100000

Il troncamento approssimativo con ~ è di solito più economico del troncamento esatto. Scegli la conservazione in base alle esigenze di recupero, non alla speranza.

Le Liste di Redis sono ancora utili per code semplici

Prima che esistessero gli Streams, molte code Redis usavano liste:

LPUSH jobs:email '{"to":"[email protected]"}'
BRPOP jobs:email 5

Le liste sono ancora adatte per code molto semplici, specialmente quando hai bisogno di un comportamento di pop bloccante e non hai bisogno di gruppi di consumatori o cronologia. Il limite è il recupero. Se un worker estrae un lavoro e si blocca prima di finirlo, quel lavoro è perso a meno che tu non aggiunga una contabilità extra.

Esistono pattern che usano BRPOPLPUSH o BLMOVE per spostare i lavori in una lista di elaborazione, poi rimuoverli dopo il successo. Questi pattern possono funzionare, ma una volta che hai bisogno di tracciamento dei lavori in sospeso, tentativi e più consumatori, Streams di solito ti dà un punto di partenza più chiaro.

Scegli Redis quando la semplicità conta più delle funzionalità del broker

La messaggistica Redis è interessante quando Redis fa già parte del tuo stack e il carico di lavoro è modesto. Eviti di gestire un altro sistema distribuito. Gli sviluppatori conoscono già i client Redis, il monitoraggio, le credenziali e i percorsi di distribuzione.

Questa è una ragione valida. La semplicità operativa ha un valore reale.

Redis ha anche una latenza molto bassa. Se la tua applicazione e Redis sono nella stessa regione o rete privata, pubblicare una piccola notifica è di solito economico e veloce. Per l'invalidazione della cache o gli aggiornamenti di stato in tempo reale, un broker più pesante potrebbe essere superfluo.

Redis ti permette anche di combinare cambiamenti di stato e messaggi con attenzione. Uno script Lua o una transazione può aggiornare una chiave e aggiungere a uno stream in un'unica operazione lato Redis. Questo può essere utile per piccoli sistemi dove Redis è il detentore centrale dello stato.

Il problema è che Redis non dovrebbe diventare il tuo broker accidentale per tutto. Se ogni servizio inizia ad aggiungere stream ad alto volume senza un piano di conservazione, la scelta "semplice" diventa un archivio di log in memoria sovraccarico.

Scegli un broker dedicato quando la gestione dei fallimenti è il prodotto

Kafka, RabbitMQ, Pulsar, NATS JetStream e i servizi di coda cloud esistono perché la messaggistica diventa rapidamente complessa.

Usa un broker dedicato quando hai bisogno di funzionalità come:

  • Conservazione a lungo termine misurata in settimane, mesi o anni.
  • Cronologia dei messaggi molto più grande della memoria.
  • Code di lettere morte e politiche di ripetizione integrate nel broker.
  • Consegna ritardata, priorità, chiavi di routing, exchange o partizionamento degli argomenti.
  • Pattern di replica cross-regione progettati per la messaggistica.
  • Molti gruppi di consumatori indipendenti che riproducono la stessa cronologia degli eventi.
  • Strumenti più potenti per lag, offset, ribilanciamento e audit.

Kafka è di solito una scelta migliore per pipeline di eventi ad alto volume e log riproducibili. RabbitMQ è spesso una scelta migliore per routing sofisticato, riconoscimenti e code di lavoro. Le code cloud sono spesso migliori quando vuoi durabilità gestita e confini operativi semplici.

Redis Streams può gestire carichi di lavoro di produzione utili, ma è pur sempre Redis. I suoi dati sono centrati sulla memoria, le sue impostazioni di persistenza devono essere comprese e le sue funzionalità da broker sono intenzionalmente più ridotte rispetto ai sistemi dedicati.

Un modo concreto per decidere

Fai queste domande prima di scegliere Redis:

  1. Un consumatore può perdere un messaggio senza perdita di dati?
  2. Un consumatore disconnesso deve recuperare?
  3. Per quanto tempo devono essere conservati i messaggi?
  4. I dati dei messaggi conservati possono stare comodamente nella memoria di Redis?
  5. I worker gestiscono i messaggi duplicati in modo sicuro?
  6. Hai bisogno di code di lettere morte, tentativi ritardati, priorità o regole di routing?
  7. Questo traffico interferirà con la cache o le sessioni di Redis?

Se i messaggi persi sono accettabili, Pub/Sub potrebbe essere sufficiente.

Se i consumatori devono recuperare e la conservazione è limitata, Streams potrebbe essere sufficiente.

Se i dati dei messaggi necessitano di conservazione a lungo termine, replay da parte di molti team, comportamento complesso del broker o forte separazione operativa, usa un broker dedicato.

Esempio: invalidazione della cache

Un'applicazione memorizza le pagine dei prodotti nella memoria di processo locale e in Redis. Quando un prodotto cambia, il servizio di amministrazione pubblica:

PUBLISH cache:invalidate product:123

Ogni istanza web iscritta a cache:invalidate elimina la sua copia locale. Se un'istanza web perde il messaggio, la sua voce locale ha ancora un TTL di cinque minuti e controlla anche un campo di versione del prodotto alla prossima richiesta. Pub/Sub va bene perché esiste un percorso di recupero.

Usare Kafka qui aggiungerebbe probabilmente più peso operativo che valore.

Esempio: lavori email in background

Un utente si registra e devi inviare un'email di benvenuto. Se il worker è giù per un minuto, il lavoro deve comunque essere inviato in seguito. Pub/Sub è una scelta inadeguata.

Uno Stream Redis può funzionare:

XADD email:jobs MAXLEN ~ 100000 * job_id abc123 type welcome user_id 42

I worker leggono attraverso un gruppo di consumatori, inviano l'email, registrano job_id come completato e chiamano XACK. Un monitor controlla i lavori in sospeso e recupera quelli vecchi. Questo è ragionevole per una coda interna modesta.

Se la consegna delle email diventa su larga scala, necessita di tentativi ritardati, gestione delle lettere morte, limiti di velocità per cliente e dashboard operativi ricchi, una coda dedicata inizia a sembrare migliore.

Esempio: eventi di audit

Gli eventi di audit di solito necessitano di durabilità, ricerca, conservazione e talvolta gestione legale o di conformità. Redis Streams può aiutare come buffer breve, ma Redis non dovrebbe essere l'archivio finale degli audit. Usa un log durevole, database, pipeline di object storage o servizio di eventi gestito progettato per conservazione e revisione.

Note operative se scegli Redis

Per Pub/Sub:

  • Configura client-output-buffer-limit pubsub.
  • Usa connessioni subscriber dedicate.
  • Costruisci comportamento di riconnessione e reiscrizione.
  • Tratta i messaggi come suggerimenti, non fatti durevoli.

Per Streams:

  • Imposta una politica di conservazione con MAXLEN, MINID o troncamento esplicito.
  • Monitora le voci in sospeso.
  • Rendi i consumatori idempotenti.
  • Usa XACK solo dopo che il lavoro ha successo.
  • Pianifica come i messaggi bloccati vengono rivendicati e ritentati.
  • Controlla memoria, persistenza e lag di replica.

Redis è un buon message broker quando scegli la parte di Redis che corrisponde al lavoro. Pub/Sub è un segnale in diretta. Streams sono un log durevole limitato. Nessuno dei due dovrebbe essere scelto solo perché Redis è già in esecuzione, ma entrambi possono essere la risposta corretta più semplice quando il loro modello di fallimento corrisponde alla tua applicazione.

Il terreno di mezzo scomodo

Molti team si trovano nel mezzo: Pub/Sub è troppo soggetto a perdite, Kafka sembra troppo grande e RabbitMQ sembra un sistema in più da gestire. Redis Streams può essere una buona risposta lì, ma solo se lo tratti come una vera coda e non come una lista magica.

Un design sano degli Streams ha la proprietà di questi dettagli:

  • Chi crea lo stream e il gruppo di consumatori?
  • Quanti consumatori sono previsti?
  • Qual è l'età massima in sospeso prima che un messaggio venga reclamato?
  • Cosa succede dopo un fallimento ripetuto?
  • Quanta cronologia dello stream viene conservata?
  • Quale dashboard o avviso mostra un lag crescente?

Senza queste risposte, gli Streams possono fallire silenziosamente. Un worker può leggere i messaggi e bloccarsi prima di XACK, lasciando le voci in sospeso per sempre. Un altro worker potrebbe non rivendicarle mai. La lunghezza dello stream può continuare a crescere perché nessuno ha configurato il troncamento. La memoria di Redis aumenta, ma il team dell'applicazione pensa "la coda è durevole", quindi non se ne accorgono fino a quando l'istanza è sotto pressione.

Un worker semplice dovrebbe di solito fare questo ciclo:

leggi un piccolo batch
elabora ogni messaggio in modo idempotente
riconosci solo i messaggi riusciti
ispeziona periodicamente i messaggi in sospeso
rivendica i messaggi in sospeso bloccati
tronca secondo la politica di conservazione

Questo è più lavoro di Pub/Sub, e questo è il punto. La durabilità sposta sempre la complessità da qualche parte. Redis Streams mantiene il lato broker abbastanza piccolo, ma l'applicazione possiede ancora tentativi, comportamento delle lettere morte e idempotenza.

Se nessuno nel team vuole possedere questi dettagli, una coda gestita potrebbe essere più economica a lungo termine anche se sembra più pesante il primo giorno. Il miglior broker non è il più veloce in un benchmark. È quello il cui comportamento di fallimento il tuo team può gestire alle 3 del mattino senza indovinare.