RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster

Failover e alta disponibilità sono argomenti complessi, quindi dedicheremo articoli separati a RabbitMQ e Kafka. Questo articolo riguarda RabbitMQ, mentre il prossimo tratterà Kafka, in comparazione con RabbitMQ. L'articolo è lungo, quindi mettiti comodo.

Esaminiamo le strategie di tolleranza ai guasti, coerenza e alta disponibilità (HA), nonché i compromessi necessari in ciascuna strategia. RabbitMQ può funzionare su un cluster di nodi e viene quindi classificato come sistema distribuito. Quando parliamo di sistemi distribuiti, spesso discorriamo di coerenza e disponibilità.

Questi concetti descrivono come un sistema si comporta in caso di guasto. La perdita di connessione di rete, il guasto di un server, il malfunzionamento di un disco rigido, l'indisponibilità temporanea del server a causa di garbage collection, la perdita di pacchetti o il rallentamento della connessione di rete. Tutti questi eventi possono portare a perdita di dati o conflitti. Risulta praticamente impossibile avere un sistema che sia simultaneamente completamente coerente (senza perdita di dati, senza discrepanze) e disponibile (capace di accettare operazioni di lettura e scrittura) in tutti i casi di guasto.

Vedremo che la coerenza e la disponibilità si trovano agli estremi opposti dello spettro, e dovrete scegliere in quale direzione ottimizzare. La buona notizia è che con RabbitMQ è possibile fare questa scelta. Avete a disposizione alcuni «interruttori nerd» per spostare l'equilibrio verso una maggiore coerenza o una maggiore disponibilità.

Presteremo particolare attenzione a quali configurazioni portano alla perdita di dati a causa delle registrazioni confermate. C'è una catena di responsabilità tra publisher, broker e consumatori. Dopo che il messaggio è stato inviato al broker, è compito di quest'ultimo non perdere il messaggio. Quando il broker conferma al publisher la ricezione del messaggio, non ci aspettiamo che venga perso. Ma vedremo che questo può effettivamente accadere a seconda della configurazione del vostro broker e publisher.

Primitivi di resilienza di un singolo nodo

Code/instradamento resilienti

In RabbitMQ ci sono due tipi di code: durevoli (durable) e non durevoli (non-durable). Tutte le code vengono memorizzate nel database Mnesia. Le code durevoli vengono ripristinate all'avvio del nodo e, quindi, sopravvivono al riavvio, al guasto del sistema o al crash del server (fino a quando i dati vengono memorizzati). Questo significa che finché dichiari la routinizzazione (exchange) e la coda come durevoli, l'infrastruttura delle code/routinizzazione tornerà in esecuzione.

Le code e la routinizzazione non durevoli vengono eliminate al riavvio del nodo.

Messaggi durevoli

Il fatto che una coda sia durevole non significa che tutti i suoi messaggi sopravvivano al riavvio del nodo. Saranno ripristinati solo i messaggi contrassegnati dal publisher come durevoli (persistent). I messaggi durevoli creano effettivamente un carico aggiuntivo sul broker, ma se la perdita di messaggi è inaccettabile, non c'è altra soluzione.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 1. Matrice di durevolezza

Clusterizzazione con mirroring della coda

Per affrontare la perdita di un broker, abbiamo bisogno di ridondanza. Possiamo unire più nodi RabbitMQ in un cluster e poi aggiungere ulteriore ridondanza replicando le code tra più nodi. In questo modo, se un nodo fallisce, non perdiamo dati e rimaniamo accessibili.

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 esistono per scalabilità, ma esclusivamente per ridondanza.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 2. Mirroring della coda

Il mirroring è impostato tramite la politica appropriata. Qui è possibile scegliere il fattore di replica e persino i nodi su cui deve risiedere la coda. Esempi:

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

Conferma al publisher

Per garantire una registrazione coerente, è necessaria la conferma da parte del publisher (Publisher Confirms). Senza di essa, c'è il rischio di perdere messaggi. La conferma viene inviata al publisher dopo che il messaggio è stato registrato su disco. RabbitMQ registra i messaggi su disco non al momento della ricezione, ma in modo periodico, nell'ordine di centinaia di millisecondi. Quando la coda è mirrorata, la conferma viene inviata solo dopo che tutti i mirror hanno registrato la propria copia del messaggio su disco. Questo significa che l'uso delle conferme aggiunge latenza, ma se la sicurezza dei dati è importante, sono indispensabili.

Coda a prova di guasto

Quando il broker si arresta o si guasta, tutte le code master su questo nodo si disconnettono con esso. Il cluster quindi seleziona il mirror più vecchio di ogni master e lo promuove come nuovo master.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 3. Diverse code mirrorate e le loro politiche

Il broker 3 è andato giù. Si noti che lo specchio della coda C sul broker 2 è stato elevato a master. Inoltre, è stato creato un nuovo specchio per la coda C sul broker 1. RabbitMQ cerca sempre di mantenere il tasso di replicazione indicato nelle vostre politiche.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 4. Il broker 3 crolla, causando il fallimento della coda C

Il broker 1 sta cadendo! Ci rimane solo un broker. Lo specchio della coda B è elevato a master.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 5

Abbiamo recuperato il broker 1. Indipendentemente da quanto bene i dati abbiano sopportato la perdita e il ripristino del broker, tutti i messaggi specchiati della coda vengono scartati al riavvio. È importante notare questo, poiché avrà delle conseguenze. Esamineremo presto queste conseguenze. Pertanto, il broker 1 è ora di nuovo un membro del cluster, e il cluster cerca di rispettare le politiche e quindi crea specchi sul broker 1.

In questo caso, la perdita del broker 1 è stata totale, così come i dati, quindi la coda B non specchiata è stata completamente persa.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 6. Il broker 1 torna in funzione

Il Broker 3 è tornato online, quindi le code A e B stanno ricevendo nuovamente i mirror creati su di esso per soddisfare le loro politiche di HA. Ma ora tutte le code principali sono su un singolo nodo! Questo non è ideale, sarebbe meglio una distribuzione uniforme tra i nodi. Sfortunatamente, non ci sono opzioni speciali per il riequilibrio dei master. Torneremo su questo argomento più avanti, poiché prima dobbiamo considerare la sincronizzazione della coda.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 7. Il Broker 3 torna online. Tutte le code principali su un singolo nodo!

Così ora dovreste avere un'idea di come i mirror garantiscano ridondanza e tolleranza ai guasti. Ciò assicura la disponibilità in caso di guasto di un nodo e protegge dalla perdita di dati. Ma non abbiamo ancora finito, perché in realtà è tutto molto più complicato.

Sincronizzazione

Quando si crea un nuovo specchio, tutti i nuovi messaggi verranno sempre replicati su questo specchio e su qualsiasi altro. Per quanto riguarda i dati esistenti nella coda principale, possiamo replicarli nel nuovo specchio, che diventa una copia completa del master. Possiamo anche decidere di non replicare i messaggi esistenti e permettere alla coda principale e al nuovo specchio di allinearsi nel tempo, mentre nuovi messaggi arrivano in coda e i messaggi esistenti escono dalla testa della coda principale.

Tale sincronizzazione può essere eseguita automaticamente o manualmente e gestita tramite la politica delle code. Consideriamo un esempio.

Abbiamo due code specchiate. La Coda A si sincronizza automaticamente, mentre la Coda B manualmente. In entrambe le code ci sono dieci messaggi.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 8. Due code con diversi modalità di sincronizzazione

Ora stiamo perdendo il Broker 3.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 9. Il Broker 3 è andato offline

Il Broker 3 torna in funzione. Il cluster crea uno specchio per ogni coda su un nuovo nodo e sincronizza automaticamente la nuova Coda A con il master. Tuttavia, lo specchio della nuova Coda B rimane vuoto. Pertanto, abbiamo una completa ridondanza della Coda A e solo uno specchio per i messaggi esistenti nella Coda B.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 10. Il nuovo specchio della Coda A riceve tutti i messaggi esistenti, mentre il nuovo specchio della Coda B no.

Entrambe le code ricevono ulteriori dieci messaggi. Poi il Broker 2 si guasta, e la Coda A torna al suo specchio più vecchio, che si trova sul Broker 1. In caso di guasto, non si verifica alcuna perdita di dati. Nella Coda B ci sono venti messaggi nel master e solo dieci nello specchio, poiché questa coda non ha mai replicato i dieci messaggi originali.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 11. La Coda A torna al Broker 1 senza perdita di messaggi.

Entrambe le code ricevono ulteriori dieci messaggi. Ora il Broker 1 si guasta. La Coda A passa senza problemi allo specchio senza perdita di messaggi. Tuttavia, la Coda B incontra problemi. A questo punto possiamo ottimizzare la disponibilità o la coerenza.

Se vogliamo ottimizzare la disponibilità, dobbiamo impostare la politica ha-promote-on-failure su always. Questo valore è predefinito, quindi possiamo anche non specificare affatto la politica. In tal caso, sostanzialmente stiamo consentendo guasti negli specchi non sincronizzati. Questo porterà alla perdita di messaggi, ma la coda rimane disponibile per la lettura e la scrittura.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 12. La coda A retrocede sul Broker 3 senza perdita di messaggi. La coda B retrocede sul Broker 3 con la perdita di dieci messaggi.

Possiamo anche impostare ha-promote-on-failure su when-synced. In questo caso, invece di retrocedere su uno specchio, la coda attenderà che il Broker 1 con i suoi dati torni operativo. Una volta tornato, la coda principale si trova di nuovo sul Broker 1 senza perdita di dati. La disponibilità viene sacrificata per la sicurezza dei dati. Ma questo è un modo rischioso, che potrebbe portare anche a una perdita totale di dati, su cui ci soffermeremo a breve.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 13. La coda B rimane non disponibile dopo la perdita del Broker 1.

Puoi farti la domanda: «Forse è 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!

Consideriamo un esempio. Attualmente abbiamo code molto lunghe. Come possono crescere a tale dimensione? Per diversi motivi:

  • Le code non vengono utilizzate attivamente
  • Si tratta di code ad alta velocità, e in questo momento i consumatori stanno lavorando lentamente
  • Si tratta di code ad alta velocità, è avvenuto un guasto e i consumatori stanno recuperando

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 14. Due grandi code con diverse modalità di sincronizzazione

Ora si guasta il Broker 3.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 15. Il Broker 3 si guasta, lasciando un master e uno specchio in ogni coda

Il Broker 3 torna online e vengono creati nuovi specchi. La Coda Principale A inizia a replicare i messaggi esistenti su un nuovo specchio, e in quel periodo la Coda non è disponibile. La replica dei dati richiede due ore, il che porta a due ore di inattività per questa Coda!

Tuttavia, la Coda B rimane disponibile durante l'intero periodo. Ha sacrificato parte della ridondanza a favore della disponibilità.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 16. La coda rimane non disponibile durante la sincronizzazione.

Dopo due ore, anche la Coda A diventa disponibile e può riprendere le operazioni di lettura e scrittura.

Aggiornamenti

Questo comportamento bloccante durante la sincronizzazione rende difficile l'aggiornamento dei cluster con code molto grandi. A un certo punto, il nodo con il master deve essere riavviato, il che significa passare a uno specchio o disattivare la coda durante l'aggiornamento del server. Se scegliamo di passare, perderemo i messaggi se gli specchi non sono sincronizzati. Di default, durante la disattivazione del broker, il passaggio a uno specchio non sincronizzato non viene eseguito. Ciò significa che, non appena il broker torna, non perdiamo messaggi, l'unico danno subito è stato solo l'arretrato della coda. Le regole di comportamento durante la disattivazione del broker sono definite dalla politica. ha-promote-on-shutdown. È possibile impostare uno dei due valori:

  • always= attivato il passaggio a specchi non sincronizzati
  • when-synced= passaggio solo a uno specchio sincronizzato, altrimenti la coda diventa indisponibile per lettura e scrittura. La coda torna operativa non appena il broker torna disponibile

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

Quando la disponibilità aumenta la sicurezza dei dati

Prima di prendere una decisione, è necessario considerare un'ulteriore complicazione. Anche se la sincronizzazione automatica è migliore per la ridondanza, come influisce sulla sicurezza dei dati? Certamente, grazie a una maggiore ridondanza, RabbitMQ ha minori probabilità di perdere messaggi esistenti, ma che dire dei nuovi messaggi dai publisher?

A questo proposito bisogna considerare:

  • Può un publisher semplicemente restituire un errore e un servizio superiore o un utente riprovare in seguito?
  • Può un publisher memorizzare un messaggio localmente o in un database per riprovare in seguito?

Se il publisher può soltanto scartare il messaggio, allora, in realtà, migliorare la disponibilità aumenta anche la sicurezza dei dati.

Pertanto, bisogna cercare un equilibrio, e la soluzione dipende dalla situazione specifica.

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

Idea ha-promote-on-failure= when-synced consiste nel prevenire il passaggio a uno specchio non sincronizzato, evitando così la perdita di dati. La coda rimane inaccessibile per lettura o scrittura. Invece, cerchiamo di ripristinare il broker arrestato con dati intatti, affinché possa riprendere operatività come master senza perdita di dati.

Ma (e questo è un grosso ma) se il broker ha perso i suoi dati, ci troviamo di fronte a un grande problema: la coda è andata persa! Tutti i dati sono scomparsi! Anche se hai degli specchi che in gran parte raggiungono la coda principale, anche questi specchi vengono scartati.

Per riaggiungere un nodo con lo stesso nome, diciamo al cluster di dimenticare il nodo perso (con il comando rabbitmqctl forget_cluster_node) e avviare un nuovo broker con lo stesso nome host. Finché il cluster ricorda il nodo perso, ricorda anche la vecchia coda e gli specchi non sincronizzati. Quando si dice al cluster di dimenticare il nodo perso, anche questa coda viene dimenticata. Ora è necessario dichiararla di nuovo. Abbiamo perso tutti i dati, anche se avevamo specchi con un set di dati parziale. Sarebbe stato meglio passare a uno specchio non sincronizzato!

Per questo motivo, la sincronizzazione manuale (e il mancato completamento della sincronizzazione) insieme a ha-promote-on-failure=when-synced, a mio avviso, è piuttosto rischiosa. I documenti affermano che questa opzione esiste per la sicurezza dei dati, ma è un doppio gioco.

Ribilanciamento dei master

Come promesso, torniamo al problema della concentrazione di tutti i master su uno o più nodi. Questo può avvenire anche a seguito di un aggiornamento "rolling" del cluster. In un cluster con tre nodi, tutte le code principali possono accumularsi su uno o due nodi.

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

  • Non ci sono buoni strumenti per eseguire il ribilanciamento
  • Sincronizzazione delle code

Per il ribilanciamento c'è un plugin di terze parti plugin, che non è supportato ufficialmente. Per quanto riguarda i plugin di terze parti, nel manuale di RabbitMQ si dice: «Il plugin fornisce alcuni strumenti aggiuntivi per la configurazione e la reportistica, ma non è supportato e non è stato verificato dal team di RabbitMQ. Usalo a tuo rischio e pericolo».

C'è anche un altro trucco per spostare la coda principale tramite politiche HA. Ne parla il manuale script per questo. Funziona come segue:

  • Rimuove tutte le repliche utilizzando una politica temporanea con una priorità più alta rispetto alla politica HA esistente.
  • Modifica la politica temporanea HA per utilizzare la modalità "nodi" specificando il nodo su cui trasferire la coda principale.
  • Sincronizza la coda per la migrazione forzata.
  • Una volta completata la migrazione, rimuove la politica temporanea. La politica HA originale entra in vigore ed è creata la quantità necessaria di repliche.

Lo svantaggio è che questo approccio potrebbe non funzionare se hai code grandi o requisiti rigorosi di ridondanza.

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

Violazione della connettività

I nodi di un sistema distribuito si connettono tramite collegamenti di rete, e tali collegamenti possono essere disattivati. La frequenza delle disconnessioni dipende dall'infrastruttura locale o dall'affidabilità del cloud scelto. In ogni caso, i sistemi distribuiti devono essere in grado di gestirle. Ci troviamo di nuovo di fronte a una scelta tra disponibilità e coerenza, e ancora una volta la buona notizia è che RabbitMQ offre entrambe le opzioni (solo che non possono essere attive contemporaneamente).

Con RabbitMQ abbiamo due opzioni principali:

  • Consentire la divisione logica (split-brain). Questo garantisce la disponibilità, ma può provocare perdita di dati.
  • Vietare la divisione logica. Può portare a una perdita temporanea di disponibilità a seconda di come i client si connettono al cluster. Può inoltre causare una completa indisponibilità in un cluster di due nodi.

Ma cos'è la divisione logica? È quando un cluster si divide a metà a causa della perdita di collegamenti di rete. Su ciascun lato, i replica vengono promossi a master, quindi alla fine ogni coda ha più master.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 17. La coda principale e due specchi, ciascuno su un nodo separato. Poi si verifica un guasto di rete e uno specchio si disconnette. Il nodo disconnesso vede che gli altri due sono caduti e promuove i suoi specchi a master. Ora abbiamo due code principali, e entrambe consentono sia scrittura che lettura.

Se i publisher inviano dati a entrambi i master, avremo due copie divergenti della coda.

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

Modalità Ignora (predefinito)

Questa modalità garantisce disponibilità. Dopo una perdita di connettività, si verifica una divisione logica. Al ripristino della connettività, l'amministratore deve decidere quale sezione privilegiare. La parte perdente verrà riavviata e tutti i dati accumulati su quel lato andranno persi.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 18. Tre publisher sono collegati a tre broker. Internamente, il cluster indirizza tutte le richieste alla coda principale sul Broker 2.

Ora perdiamo il Broker 3. Vede che gli altri broker sono caduti e promuove il suo specchio a master. Così avviene la divisione logica.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 19. Suddivisione logica (split-brain). Le registrazioni vanno in due principali code, e due copie si disperdono.

La connettività viene ripristinata, ma la suddivisione logica rimane. L'amministratore deve scegliere manualmente il lato perdente. Nel caso qui sotto, l'amministratore riavvia il Broker 3. Tutti i messaggi che non sono stati trasmessi vengono persi.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 20. L'amministratore disconnette il Broker 3.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 21. L'amministratore riavvia il Broker 3, e si unisce al cluster, perdendo tutti i messaggi che erano presenti.

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

Modalità Autoheal

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

Modalità Pause Minority

Se non vogliamo causare una divisione logica, l'unica opzione è rinunciare alla lettura e alla scrittura sul lato minore dopo la divisione del cluster. Quando il broker rileva di trovarsi sul lato minore, sospende l'attività, chiudendo tutte le connessioni esistenti e rifiutando eventuali nuove. Una volta al secondo controlla il ripristino della connettività. Non appena la connettività è ripristinata, riprende l'attività e si riunisce al cluster.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 22. Tre publisher sono collegati a tre broker. Internamente, il cluster dirige tutte le richieste nella coda principale sul Broker 2.

Successivamente, i Broker 1 e 2 si separano dal Broker 3. Invece di elevare il proprio specchio a master, il Broker 3 sospende l'attività e diventa non disponibile.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 23. Il Broker 3 sospende l'attività, disconnette tutti i clienti e rifiuta le richieste di connessione.

Non appena la connettività viene ripristinata, ritorna nel cluster.

Vediamo un altro esempio, dove la coda principale si trova sul Broker 3.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 24. La coda principale è sul Broker 3.

Poi si verifica la stessa perdita di coerenza. Il Broker 3 va in pausa, poiché si trova sul lato minore. Dall'altra parte, i nodi vedono che il Broker 3 è caduto, quindi uno specchio più vecchio dei Broker 1 e 2 viene elevato a master.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 25. Passaggio al Broker 2 in caso di indisponibilità del Broker 3.

Quando la coerenza viene ripristinata, il Broker 3 si unirà al cluster.

RabbitMQ contro Kafka: resilienza e alta disponibilità nei cluster
Fig. 26. Il cluster è tornato alla normale operatività.

È importante capire qui che otteniamo coerenza, ma possiamo anche ottenere disponibilità, se riusciamo a trasferire con successo i client sulla maggior parte della sezione. Per la maggior parte delle situazioni, personalmente sceglierei la modalità Pause Minority, ma questo dipende davvero dal caso specifico.

Per garantire la disponibilità, è importante assicurarsi che i client si connettano con successo al nodo. Esaminiamo le nostre opzioni.

Assicurazione della coerenza dei client

Abbiamo diverse opzioni per reindirizzare i clienti alla parte principale del cluster o ai nodi operativi dopo la perdita di connettività (dopo il guasto di un nodo). Cominciamo ricordando che una coda specifica viene ospitata su un determinato nodo, ma il routing e le politiche vengono replicate su tutti i nodi. I clienti possono connettersi a qualsiasi nodo, e il routing interno li dirigerà dove necessario. Tuttavia, quando un nodo è in pausa, rifiuta le connessioni, quindi i clienti devono connettersi a un altro nodo. Se un nodo è andato giù, ha poco da fare.

Le nostre opzioni:

  • L'accesso al cluster avviene tramite un bilanciatore di carico, che cicla semplicemente attraverso i nodi, mentre i clienti riprovano a connettersi fino a un completamento riuscito. Se un nodo non funziona o è in pausa, i tentativi di connessione a quel nodo falliranno, ma i tentativi successivi verranno indirizzati ad altri server (in modalità ciclica). Questo è adatto per una perdita di connettività di breve durata o un server guasto che verrà ripristinato rapidamente.
  • Access to the cluster via a load balancer, removing suspended/dropped nodes from the list as soon as they are detected. If this is done quickly, and if clients are able to retry connections, we will achieve continuous availability.
  • Provide each client with a list of all nodes, allowing the client to randomly select one upon connection. If an error occurs during the connection attempt, the client will move on to the next node in the list until successfully connected.
  • Redirect traffic away from a dropped/suspended node using DNS. This is accomplished with a low TTL.

Conclusioni

RabbitMQ clustering has its advantages and disadvantages. The most significant drawbacks are that:

  • when joining the cluster, nodes discard their data;
  • blocking synchronization leads to queue unavailability.

Tutte le decisioni difficili derivano da queste due caratteristiche dell'architettura. Se RabbitMQ potesse salvare i dati durante la riconnessione del cluster, la sincronizzazione sarebbe più veloce. Se fosse in grado di sincronizzazione non bloccante, gestirebbe meglio le code grandi. Risolvere questi due problemi migliorerebbe notevolmente le caratteristiche di RabbitMQ come tecnologia di messaggistica resiliente e ad alta disponibilità. Non mi sentirei di raccomandare RabbitMQ con clustering nelle seguenti situazioni:

  • Una rete non affidabile.
  • Una memorizzazione non affidabile.
  • Code molto grandi.

Per quanto riguarda le impostazioni per l'alta disponibilità, considera queste:

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

Per la coerenza (sicurezza dei dati) considera le seguenti impostazioni:

  • Publisher Confirms e Manual Acknowledgements sul lato del consumatore
  • ha-promote-on-failure=when-synced, se gli editori possono riprovare più tardi e se hai uno storage molto affidabile! Altrimenti imposta =always.
  • ha-sync-mode=automatic (ma per code di inattività superiori potrebbe essere necessario il modo manuale; inoltre, considera se l'inaccessibilità potrebbe comportare la perdita di messaggi)
  • modalità Pausa Minoritaria
  • messaggi persistenti

Non abbiamo ancora affrontato tutte le questioni relative alla tolleranza ai guasti e all'alta disponibilità; ad esempio, come eseguire in sicurezza procedure di amministrazione (come gli aggiornamenti progressivi). Dobbiamo parlare anche di federazione e del plugin Shovel.

Se ho dimenticato qualcosa, per favore fammelo sapere.

Vedi anche il mio un post, dove eseguo dei test nel cluster RabbitMQ utilizzando Docker e Blockade per verificare alcuni scenari di perdita di messaggi descritti in questo articolo.

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

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster