RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster

La tolleranza agli errori e l'elevata disponibilità sono argomenti importanti, quindi dedicheremo articoli separati a RabbitMQ e Kafka. Questo articolo riguarda RabbitMQ e il successivo riguarda Kafka, rispetto a RabbitMQ. Questo è un articolo lungo, quindi mettiti comodo.

Esaminiamo le strategie di tolleranza agli errori, coerenza e alta disponibilità (HA) e i compromessi che ciascuna strategia comporta. RabbitMQ può essere eseguito su un cluster di nodi ed è quindi classificato come sistema distribuito. Quando si parla di sistemi distribuiti, si parla spesso di coerenza e disponibilità.

Questi concetti descrivono come si comporta un sistema quando fallisce. Errore di connessione di rete, errore del server, errore del disco rigido, indisponibilità temporanea del server dovuta alla garbage collection, perdita di pacchetti o rallentamento della connessione di rete. Tutto ciò può portare a perdite di dati o conflitti. Si scopre che è praticamente impossibile mettere in piedi un sistema che sia completamente coerente (nessuna perdita di dati, nessuna divergenza di dati) e disponibile (accetterà letture e scritture) per tutti gli scenari di errore.

Vedremo che coerenza e disponibilità si trovano agli estremi opposti dello spettro e devi scegliere in che modo ottimizzare. La buona notizia è che con RabbitMQ questa scelta è possibile. Hai questo tipo di leve “nerd” per spostare l’equilibrio verso una maggiore coerenza o una maggiore accessibilità.

Presteremo particolare attenzione a quali configurazioni portano alla perdita di dati a causa di record confermati. Esiste una catena di responsabilità tra editori, intermediari e consumatori. Una volta trasmesso il messaggio al broker, è suo compito non perderlo. Quando il broker conferma la ricezione del messaggio da parte dell'editore, non ci aspettiamo che vada perso. Ma vedremo che ciò può effettivamente accadere a seconda della configurazione del tuo broker e del tuo editore.

Primitive di resilienza a nodo singolo

Accodamento/routing resiliente

Esistono due tipi di code in RabbitMQ: durevoli e non durevoli. Tutte le code vengono salvate nel database Mnesia. Le code durevoli vengono nuovamente pubblicizzate all'avvio del nodo e quindi sopravvivono a riavvii, arresti anomali del sistema o arresti anomali del server (fintanto che i dati vengono persistenti). Ciò significa che finché dichiari il routing (scambio) e la coda resilienti, l'infrastruttura di coda/routing tornerà online.

Le code e l'instradamento volatili vengono rimossi al riavvio del nodo.

Messaggi persistenti

Solo perché una coda è durevole non significa che tutti i suoi messaggi sopravvivranno al riavvio del nodo. Solo i messaggi impostati dall'editore come sostenuta (persistente). I messaggi persistenti creano un carico aggiuntivo sul broker, ma se la perdita dei messaggi è inaccettabile, non c'è altra opzione.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 1. Matrice della sostenibilità

Clustering con mirroring delle code

Per sopravvivere alla perdita di un broker, abbiamo bisogno di ridondanza. Possiamo combinare più nodi RabbitMQ in un cluster e quindi aggiungere ulteriore ridondanza replicando le code tra più nodi. In questo modo, se un nodo fallisce, non perdiamo dati e rimaniamo disponibili.

Mirroring della coda:

  • una coda principale (master), che riceve tutti i comandi di scrittura e lettura
  • uno o più mirror che ricevono tutti i messaggi e i metadati dalla coda principale. Questi mirror non sono presenti per il ridimensionamento, ma esclusivamente per la ridondanza.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 2. Mirroring della coda

Il mirroring è impostato dalla policy appropriata. In esso puoi selezionare il coefficiente di replica e persino i nodi su cui dovrebbe trovarsi la coda. Esempi:

  • ha-mode: all
  • ha-mode: exactly, ha-params: 2 (un master e uno specchio)
  • ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2

Conferma dell'editore

Per ottenere una registrazione coerente, sono necessarie le conferme dell'editore. Senza di essi c'è il rischio che i messaggi vadano persi. Una conferma viene inviata all'editore dopo che il messaggio è stato scritto su disco. RabbitMQ scrive i messaggi sul disco non al momento della ricezione, ma su base periodica, nell'ordine di diverse centinaia di millisecondi. Quando viene eseguito il mirroring di una coda, viene inviato un riconoscimento solo dopo che anche tutti i mirror hanno scritto la propria copia del messaggio su disco. Ciò significa che l’utilizzo delle conferme aggiunge latenza, ma se la sicurezza dei dati è importante, allora sono necessarie.

Coda di failover

Quando un broker si chiude o si blocca, tutti i leader della coda (master) su quel nodo si bloccano insieme ad esso. Il cluster seleziona quindi il mirror più vecchio di ciascun master e lo promuove come nuovo master.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 3. Più code con mirroring e relative policy

Il Broker 3 crolla. Tieni presente che il mirror della coda C su Broker 2 viene promosso a master. Tieni inoltre presente che è stato creato un nuovo mirror per la coda C sul broker 1. RabbitMQ tenta sempre di mantenere il fattore di replica specificato nelle policy.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 4. Il broker 3 fallisce, causando il fallimento della coda C

Il prossimo Broker 1 cade! Ci è rimasto un solo broker. Il mirror della coda B viene promosso a master.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Fig. 5

Abbiamo restituito il Broker 1. Indipendentemente dalla capacità dei dati di sopravvivere alla perdita e al ripristino del broker, tutti i messaggi della coda con mirroring vengono eliminati al riavvio. Questo è importante da notare perché ci saranno delle conseguenze. Tra poco esamineremo queste implicazioni. Quindi il Broker 1 è ora di nuovo membro del cluster e il cluster tenta di rispettare le politiche e quindi crea mirror sul Broker 1.

In questo caso, la perdita del Broker 1 è stata completa, così come i dati, quindi la Coda B senza mirroring è stata completamente persa.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 6. Il broker 1 ritorna in servizio

Broker 3 è tornato online, quindi le code A e B recuperano i mirror creati su di esso per soddisfare le proprie policy HA. Ma ora tutte le code principali sono su un nodo! Questo non è l'ideale, una distribuzione uniforme tra i nodi è migliore. Sfortunatamente, non ci sono molte opzioni qui per ribilanciare i maestri. Torneremo su questo problema più tardi perché dobbiamo prima esaminare la sincronizzazione delle code.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 7. Il broker 3 ritorna in servizio. Tutte le code principali su un nodo!

Quindi ora dovresti avere un'idea di come i mirror forniscono ridondanza e tolleranza agli errori. Ciò garantisce la disponibilità in caso di guasto di un singolo nodo e protegge dalla perdita di dati. Ma non abbiamo ancora finito, perché in realtà è molto più complicato.

sincronizzazione

Quando si crea un nuovo mirror, tutti i nuovi messaggi verranno sempre replicati su questo mirror e su tutti gli altri. Per quanto riguarda i dati esistenti nella coda master, possiamo replicarli su un nuovo mirror, che diventa una copia completa del master. Possiamo anche scegliere di non replicare i messaggi esistenti e lasciare che la coda principale e il nuovo mirror convergano nel tempo, con i nuovi messaggi che arrivano in coda e i messaggi esistenti che lasciano la testa della coda principale.

Questa sincronizzazione viene eseguita automaticamente o manualmente ed è gestita utilizzando un criterio di coda. Diamo un'occhiata a un esempio.

Abbiamo due code con mirroring. La coda A viene sincronizzata automaticamente e la coda B viene sincronizzata manualmente. Entrambe le code contengono dieci messaggi.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 8. Due code con diverse modalità di sincronizzazione

Ora stiamo perdendo Broker 3.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 9. Il broker 3 è caduto

Il Broker 3 ritorna in servizio. Il cluster crea un mirror per ogni coda sul nuovo nodo e sincronizza automaticamente la nuova coda A con il master. Tuttavia, lo specchio della nuova Coda B rimane vuoto. In questo modo abbiamo una ridondanza completa sulla coda A e un solo mirror per i messaggi esistenti della coda B.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 10. Il nuovo mirror della Coda A riceve tutti i messaggi esistenti, ma il nuovo mirror della Coda B no.

Altri dieci messaggi arrivano in entrambe le code. Il Broker 2 quindi si blocca e la Coda A torna al mirror più vecchio, che si trova sul Broker 1. Non si verifica alcuna perdita di dati in caso di guasto. Nella coda B ci sono venti messaggi nel master e solo dieci nel mirror perché questa coda non ha mai replicato i dieci messaggi originali.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 11. La coda A torna al Broker 1 senza perdere messaggi

Altri dieci messaggi arrivano in entrambe le code. Adesso si blocca il Broker 1. La coda A passa facilmente al mirror senza perdere messaggi. Tuttavia, la coda B ha problemi. A questo punto possiamo ottimizzare la disponibilità o la coerenza.

Se vogliamo ottimizzare l’accessibilità, allora è la politica ha-promuovere-in-fallimento dovrebbe essere installato in sempre. Questo è il valore predefinito, quindi puoi semplicemente non specificare affatto la policy. In questo caso, stiamo essenzialmente consentendo errori nei mirror non sincronizzati. Ciò causerà la perdita dei messaggi, ma la coda rimarrà leggibile e scrivibile.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 12. La coda A viene ripristinata al Broker 3 senza perdere messaggi. La coda B torna al Broker 3 con dieci messaggi persi

Possiamo anche installare ha-promote-on-failure nel significato when-synced. In questo caso, invece di tornare al mirror, la coda attenderà finché il Broker 1 con i suoi dati ritornerà in modalità online. Dopo il suo ritorno, la coda principale torna sul Broker 1 senza alcuna perdita di dati. La disponibilità viene sacrificata a favore della sicurezza dei dati. Ma questa è una modalità rischiosa che può portare anche alla completa perdita dei dati, di cui parleremo tra poco.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 13. La coda B rimane non disponibile dopo aver perso il Broker 1

Potresti chiederti: "È meglio non utilizzare mai la sincronizzazione automatica?" La risposta è che la sincronizzazione è un'operazione bloccante. Durante la sincronizzazione, la coda principale non può eseguire alcuna operazione di lettura o scrittura!

Diamo un'occhiata a un esempio. Ora abbiamo code molto lunghe. Come possono raggiungere dimensioni del genere? Per diverse ragioni:

  • Le code non vengono utilizzate attivamente
  • Queste sono code ad alta velocità e in questo momento i consumatori sono lenti
  • Si tratta di code ad alta velocità, si è verificato un problema tecnico e i consumatori stanno recuperando terreno

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 14. Due grandi code con diverse modalità di sincronizzazione

Ora Broker 3 cade.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 15. Il broker 3 cade, lasciando un master e un mirror in ciascuna coda

Broker 3 torna online e vengono creati nuovi mirror. La coda principale A inizia a replicare i messaggi esistenti sul nuovo mirror e durante questo periodo la coda non è disponibile. Sono necessarie due ore per replicare i dati, con conseguente due ore di inattività per questa coda!

La Coda B resta comunque disponibile per tutto il periodo. Ha sacrificato un po' di ridondanza per l'accessibilità.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 16. La coda rimane non disponibile durante la sincronizzazione

Dopo due ore, anche la Coda A diventa disponibile e può iniziare ad accettare nuovamente letture e scritture.

Aggiornamenti

Questo comportamento di blocco durante la sincronizzazione rende difficile l'aggiornamento dei cluster con code molto grandi. Ad un certo punto, il nodo master deve essere riavviato, il che significa passare a un mirror o disabilitare la coda mentre il server viene aggiornato. Se scegliamo la transizione, perderemo i messaggi se i mirror non saranno sincronizzati. Per impostazione predefinita, durante un'interruzione del broker, non viene eseguito il failover su un mirror non sincronizzato. Questo significa che appena il broker ritorna non perdiamo nessun messaggio, l'unico danno è stata una semplice coda. Le regole di comportamento quando un broker è disconnesso sono stabilite dalla policy ha-promote-on-shutdown. È possibile impostare uno dei due valori:

  • always= la transizione ai mirror non sincronizzati è abilitata
  • when-synced= passaggio solo ad un mirror sincronizzato, altrimenti la coda diventa illeggibile e non scrivibile. La coda ritorna in servizio non appena ritorna il broker

In un modo o nell'altro, con code di grandi dimensioni devi scegliere tra perdita di dati e indisponibilità.

Quando la disponibilità migliora la sicurezza dei dati

C’è un’altra complicazione da considerare prima di prendere una decisione. Sebbene la sincronizzazione automatica sia migliore per la ridondanza, che impatto ha sulla sicurezza dei dati? Naturalmente, con una migliore ridondanza, RabbitMQ ha meno probabilità di perdere i messaggi esistenti, ma per quanto riguarda i nuovi messaggi degli editori?

Qui è necessario considerare quanto segue:

  • L'editore potrebbe semplicemente restituire un errore e chiedere al servizio upstream o all'utente di riprovare più tardi?
  • L'editore può salvare il messaggio localmente o in un database per riprovare più tardi?

Se l’editore può solo scartare il messaggio, in effetti, migliorare l’accessibilità migliora anche la sicurezza dei dati.

Occorre quindi cercare un equilibrio e la soluzione dipende dalla situazione specifica.

Problemi con ha-promote-on-failure=when-sync

Idea ha-promuovere-in-fallimento= quando sincronizzato è che evitiamo il passaggio a un mirror non sincronizzato e quindi evitiamo la perdita di dati. La coda rimane illeggibile o scrivibile. Cerchiamo invece di recuperare il broker andato in crash con i suoi dati intatti in modo che possa riprendere a funzionare come master senza perdita di dati.

Ma (e questo è un grosso ma) se il broker ha perso i suoi dati, allora abbiamo un grosso problema: la coda è persa! Tutti i dati sono spariti! Anche se si hanno mirror che per lo più raggiungono la coda principale, anche questi mirror vengono scartati.

Per aggiungere nuovamente un nodo con lo stesso nome, diciamo al cluster di dimenticare il nodo perduto (con il comando conigliomqctl dimentica_cluster_node) e avviare un nuovo broker con lo stesso nome host. Mentre il cluster ricorda il nodo perduto, ricorda la vecchia coda e i mirror non sincronizzati. Quando a un cluster viene detto di dimenticare un nodo orfano, anche quella coda viene dimenticata. Ora dobbiamo dichiararlo nuovamente. Abbiamo perso tutti i dati, anche se avevamo dei mirror con un set parziale di dati. Sarebbe meglio passare ad uno specchio non sincronizzato!

Pertanto, la sincronizzazione manuale (e la mancata sincronizzazione) in combinazione con ha-promote-on-failure=when-synced, secondo me, è piuttosto rischioso. I documenti dicono che questa opzione esiste per la sicurezza dei dati, ma è un coltello a doppio taglio.

Riequilibrio magistrale

Come promesso, torniamo al problema dell'accumulo di tutti i master su uno o più nodi. Ciò può verificarsi anche a seguito di un aggiornamento in sequenza del cluster. In un cluster a tre nodi, tutte le code master si accumuleranno su uno o due nodi.

Il ribilanciamento dei master può essere problematico per due motivi:

  • Non esistono strumenti validi per eseguire il riequilibrio
  • Sincronizzazione della coda

C'è una terza parte per il riequilibrio plug-in, che non è ufficialmente supportato. Per quanto riguarda i plugin di terze parti nel manuale RabbitMQ è detto: "Il plugin fornisce alcuni strumenti aggiuntivi di configurazione e reporting, ma non è supportato o verificato dal team RabbitMQ. Utilizzare a proprio rischio."

Esiste un altro trucco per spostare la coda principale attraverso le policy HA. Il manuale menziona copione per questo. Funziona così:

  • Rimuove tutti i mirror utilizzando una policy temporanea che ha una priorità più alta rispetto alla policy HA esistente.
  • Modifica la policy temporanea HA per utilizzare la modalità nodo, specificando il nodo a cui deve essere trasferita la coda master.
  • Sincronizza la coda per la migrazione push.
  • Al termine della migrazione, elimina la policy temporanea. La politica HA iniziale diventa effettiva e viene creato il numero richiesto di mirror.

Lo svantaggio è che questo approccio potrebbe non funzionare se si hanno code di grandi dimensioni o severi requisiti di ridondanza.

Ora vediamo come funzionano i cluster RabbitMQ con le partizioni di rete.

Perdita di connettività

I nodi di un sistema distribuito sono collegati tramite collegamenti di rete e i collegamenti di rete possono e saranno disconnessi. La frequenza delle interruzioni dipende dall'infrastruttura locale o dall'affidabilità del cloud selezionato. In ogni caso, i sistemi distribuiti devono essere in grado di farvi fronte. Ancora una volta dobbiamo scegliere tra disponibilità e coerenza, e ancora una volta la buona notizia è che RabbitMQ fornisce entrambe le opzioni (ma non contemporaneamente).

Con RabbitMQ abbiamo due opzioni principali:

  • Consentire la divisione logica (split-brain). Ciò garantisce la disponibilità, ma potrebbe causare la perdita di dati.
  • Disabilita la separazione logica. Potrebbe comportare una perdita di disponibilità a breve termine a seconda della modalità di connessione dei client al cluster. Può anche portare alla completa indisponibilità in un cluster a due nodi.

Ma cos’è la separazione logica? Questo avviene quando un cluster si divide in due a causa della perdita delle connessioni di rete. Su ciascun lato, gli specchi vengono promossi a maestro, in modo che alla fine ci siano più maestri per turno.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 17. Coda principale e due mirror, ciascuno su un nodo separato. Quindi si verifica un errore di rete e uno mirror si stacca. Il nodo separato vede che gli altri due sono caduti e promuove i suoi specchi al master. Ora abbiamo due code principali, sia scrivibili che leggibili.

Se gli editori inviano dati ad entrambi i master, ci ritroveremo con due copie divergenti della coda.

Le diverse modalità di RabbitMQ forniscono disponibilità o coerenza.

Modalità Ignora (predefinita)

Questa modalità garantisce l'accessibilità. Dopo la perdita della connettività avviene una separazione logica. Una volta ripristinata la connettività, l'amministratore deve decidere a quale partizione dare la priorità. Il lato perdente verrà riavviato e tutti i dati accumulati su quel lato andranno persi.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 18. Tre editori sono associati a tre intermediari. Internamente, il cluster instrada tutte le richieste alla coda principale sul Broker 2.

Ora stiamo perdendo il Broker 3. Vede che gli altri broker sono caduti e promuove il suo mirror a master. Ecco come avviene una separazione logica.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 19. Divisione logica (split-brain). I record entrano in due code principali e le due copie divergono.

La connettività viene ripristinata, ma rimane la separazione logica. L'amministratore deve selezionare manualmente la parte perdente. Nel caso seguente, l'amministratore riavvia Broker 3. Tutti i messaggi che non è riuscito a trasmettere vanno persi.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 20. L'amministratore disabilita Broker 3.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 21. L'amministratore avvia Broker 3 e si unisce al cluster, perdendo tutti i messaggi rimasti lì.

Durante la perdita di connettività e dopo il suo ripristino, il cluster e questa coda erano disponibili per la lettura e la scrittura.

Modalità di riparazione automatica

Funziona in modo simile alla modalità Ignora, tranne per il fatto che il cluster stesso sceglie automaticamente il lato perdente dopo la divisione e il ripristino della connettività. Il lato perdente ritorna vuoto nel cluster e la coda perde tutti i messaggi inviati solo a quel lato.

Metti in pausa la modalità minoranza

Se non vogliamo consentire il partizionamento logico, la nostra unica opzione è scartare letture e scritture sul lato più piccolo dopo la partizione del cluster. Quando il broker vede che è dalla parte più piccola, sospende il lavoro, cioè chiude tutte le connessioni esistenti e rifiuta quelle nuove. Una volta al secondo verifica il ripristino della connettività. Una volta ripristinata la connettività, riprende il funzionamento e si unisce al cluster.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 22. Tre editori sono associati a tre intermediari. Internamente, il cluster instrada tutte le richieste alla coda principale sul Broker 2.

I Broker 1 e 2 si dividono quindi dal Broker 3. Invece di promuovere il proprio mirror a master, il Broker 3 lo sospende e diventa non disponibile.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 23. Broker 3 mette in pausa, disconnette tutti i client e rifiuta le richieste di connessione.

Una volta ripristinata la connettività, ritorna al cluster.

Diamo un'occhiata ad un altro esempio in cui la coda principale è su Broker 3.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 24. Coda principale sul Broker 3.

Quindi si verifica la stessa perdita di connettività. Il broker 3 fa una pausa perché è sul lato più piccolo. Dall'altro lato, i nodi vedono che il Broker 3 è caduto, quindi il mirror più vecchio dei Broker 1 e 2 viene promosso a master.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 25. Transizione al Broker 2 se il Broker 3 non è disponibile.

Una volta ripristinata la connettività, Broker 3 si unirà al cluster.

RabbitMQ vs Kafka: tolleranza agli errori e alta disponibilità nei cluster
Riso. 26. Il cluster è tornato al normale funzionamento.

La cosa importante da capire qui è che otteniamo coerenza, ma possiamo anche ottenere disponibilità, se Trasferiremo con successo i clienti alla maggior parte della sezione. Per la maggior parte delle situazioni, personalmente sceglierei la modalità Pause Minority, ma dipende davvero dal singolo caso.

Per garantire la disponibilità, è importante garantire che i client si connettano correttamente all'host. Diamo un'occhiata alle nostre opzioni.

Garantire la connettività del cliente

Abbiamo diverse opzioni su come indirizzare i client alla parte principale del cluster o ai nodi funzionanti (dopo che un nodo si guasta) dopo una perdita di connettività. Innanzitutto, ricordiamo che una coda specifica è ospitata su un nodo specifico, ma il routing e le policy vengono replicati su tutti i nodi. I client possono connettersi a qualsiasi nodo e il routing interno li indirizzerà dove devono andare. Ma quando un nodo è sospeso, rifiuta le connessioni, quindi i client devono connettersi a un altro nodo. Se il nodo cade, c'è poco che possa fare.

Le nostre opzioni:

  • Si accede al cluster utilizzando un sistema di bilanciamento del carico che scorre semplicemente attraverso i nodi e i client riprovano a connettersi fino a quando non riescono. Se un nodo è inattivo o sospeso, i tentativi di connessione a quel nodo falliranno, ma i tentativi successivi andranno ad altri server (in modalità round robin). Questo è adatto per una perdita di connettività a breve termine o per un server inattivo che verrà ripristinato rapidamente.
  • Accedi al cluster tramite un bilanciatore del carico e rimuovi i nodi sospesi/guasti dall'elenco non appena vengono rilevati. Se lo facciamo rapidamente e se i clienti sono in grado di riprovare la connessione, otterremo una disponibilità costante.
  • Fornisci a ciascun client un elenco di tutti i nodi e il client ne seleziona casualmente uno durante la connessione. Se riceve un errore durante il tentativo di connessione, passa al nodo successivo nell'elenco finché non si connette.
  • Rimuovere il traffico da un nodo guasto/sospeso utilizzando DNS. Questo viene fatto utilizzando un piccolo TTL.

risultati

Il clustering RabbitMQ presenta vantaggi e svantaggi. Gli svantaggi più gravi sono che:

  • quando si uniscono a un cluster, i nodi scartano i propri dati;
  • il blocco della sincronizzazione fa sì che la coda diventi non disponibile.

Tutte le decisioni difficili derivano da queste due caratteristiche architettoniche. Se RabbitMQ potesse salvare i dati quando il cluster viene ricongiunto, la sincronizzazione sarebbe più veloce. Se fosse in grado di effettuare una sincronizzazione senza blocchi, supporterebbe meglio code di grandi dimensioni. La risoluzione di questi due problemi migliorerebbe notevolmente le prestazioni di RabbitMQ come tecnologia di messaggistica tollerante ai guasti e altamente disponibile. Sarei riluttante a raccomandare RabbitMQ con il clustering nelle seguenti situazioni:

  • Rete inaffidabile.
  • Archiviazione inaffidabile.
  • Code molto lunghe.

Per quanto riguarda le impostazioni di disponibilità elevata, considerare quanto segue:

  • ha-promote-on-failure=always
  • ha-sync-mode=manual
  • cluster_partition_handling=ignore (o autoheal)
  • messaggi persistenti
  • garantire che i client si connettano al nodo attivo quando alcuni nodi falliscono

Per coerenza (sicurezza dei dati), considerare le seguenti impostazioni:

  • Conferme dell'editore e riconoscimenti manuali da parte del consumatore
  • ha-promote-on-failure=when-synced, se gli editori possono riprovare più tardi e se disponi di uno spazio di archiviazione molto affidabile! Altrimenti metti =always.
  • ha-sync-mode=automatic (ma per code inattive di grandi dimensioni, potrebbe essere necessaria la modalità manuale; inoltre, considerare se l'indisponibilità causerà la perdita dei messaggi)
  • Metti in pausa la modalità Minoranza
  • messaggi persistenti

Non abbiamo ancora trattato tutte le questioni relative alla tolleranza agli errori e all'alta disponibilità; ad esempio, come eseguire in modo sicuro le procedure amministrative (come gli aggiornamenti continui). Dobbiamo anche parlare della federazione e del plugin Shovel.

Se mi sono perso qualcos'altro, per favore fatemelo sapere.

Vedi anche il mio inviare, in cui eseguo un caos su un cluster RabbitMQ utilizzando Docker e Blockade per testare alcuni degli scenari di perdita di messaggi descritti in questo articolo.

Articoli precedenti della serie:
N. 1 - habr.com/ru/company/itsumma/blog/416629
N. 2 - habr.com/ru/company/itsumma/blog/418389
N. 3 - habr.com/ru/company/itsumma/blog/437446

Fonte: habr.com

Aggiungi un commento