{"id":52525,"date":"2019-11-10T00:00:00","date_gmt":"2019-11-09T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah"},"modified":"2020-02-18T14:00:16","modified_gmt":"2020-02-18T11:00:16","slug":"rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","title":{"rendered":"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d8e584d210a6a016a962ad6f956a2078.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nFailover e alta disponibilit\u00e0 sono argomenti complessi, quindi dedicheremo articoli separati a RabbitMQ e Kafka. Questo articolo riguarda RabbitMQ, mentre il prossimo tratter\u00e0 Kafka, in comparazione con RabbitMQ. L'articolo \u00e8 lungo, quindi mettiti comodo.<\/p>\n<p>Esaminiamo le strategie di tolleranza ai guasti, coerenza e alta disponibilit\u00e0 (HA), nonch\u00e9 i compromessi necessari in ciascuna strategia. RabbitMQ pu\u00f2 funzionare su un cluster di nodi e viene quindi classificato come sistema distribuito. Quando parliamo di sistemi distribuiti, spesso discorriamo di coerenza e disponibilit\u00e0. <\/p>\n<p>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\u00e0 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.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nVedremo che la coerenza e la disponibilit\u00e0 si trovano agli estremi opposti dello spettro, e dovrete scegliere in quale direzione ottimizzare. La buona notizia \u00e8 che con RabbitMQ \u00e8 possibile fare questa scelta. Avete a disposizione alcuni \u00abinterruttori nerd\u00bb per spostare l'equilibrio verso una maggiore coerenza o una maggiore disponibilit\u00e0.<\/p>\n<p>Presteremo particolare attenzione a quali configurazioni portano alla perdita di dati a causa delle registrazioni confermate. C'\u00e8 una catena di responsabilit\u00e0 tra publisher, broker e consumatori. Dopo che il messaggio \u00e8 stato inviato al broker, \u00e8 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\u00f2 effettivamente accadere a seconda della configurazione del vostro broker e publisher.<\/p>\n<h1>Primitivi di resilienza di un singolo nodo<\/h1>\n<p><\/p>\n<h3>Code\/instradamento resilienti<\/h3>\n<p>\nIn 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\u00e9 dichiari la routinizzazione (exchange) e la coda come durevoli, l'infrastruttura delle code\/routinizzazione torner\u00e0 in esecuzione.<\/p>\n<p>Le code e la routinizzazione non durevoli vengono eliminate al riavvio del nodo.<\/p>\n<h3>Messaggi durevoli<\/h3>\n<p>\nIl 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 <i>durevoli<\/i> (persistent). I messaggi durevoli creano effettivamente un carico aggiuntivo sul broker, ma se la perdita di messaggi \u00e8 inaccettabile, non c'\u00e8 altra soluzione.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8b8e2de4ef82bf8497960657aac0ddb0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 1. Matrice di durevolezza<\/i><\/p>\n<h1>Clusterizzazione con mirroring della coda<\/h1>\n<p>\nPer affrontare la perdita di un broker, abbiamo bisogno di ridondanza. Possiamo unire pi\u00f9 nodi RabbitMQ in un cluster e poi aggiungere ulteriore ridondanza replicando le code tra pi\u00f9 nodi. In questo modo, se un nodo fallisce, non perdiamo dati e rimaniamo accessibili. <\/p>\n<p>Mirroring della coda:<\/p>\n<ul>\n<li>una coda principale (master) che riceve tutti i comandi di scrittura e lettura\n<\/li>\n<li>uno o pi\u00f9 mirror che ricevono tutti i messaggi e i metadati dalla coda principale. Questi mirror non esistono per scalabilit\u00e0, ma esclusivamente per ridondanza.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/35f3d4bdc4f5e10da0e40eb91c5d8280.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 2. Mirroring della coda<\/i><\/p>\n<p>Il mirroring \u00e8 impostato tramite la politica appropriata. Qui \u00e8 possibile scegliere il fattore di replica e persino i nodi su cui deve risiedere la coda. Esempi:<\/p>\n<ul>\n<li><code>ha-mode: all<\/code>\n<\/li>\n<li><code>ha-mode: exactly, ha-params: 2<\/code> (un master e un mirror)\n<\/li>\n<li><code>ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2<\/code><\/li>\n<\/ul>\n<p><\/p>\n<h1>Conferma al publisher<\/h1>\n<p>\nPer garantire una registrazione coerente, \u00e8 necessaria la conferma da parte del publisher (Publisher Confirms). Senza di essa, c'\u00e8 il rischio di perdere messaggi. La conferma viene inviata al publisher dopo che il messaggio \u00e8 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 \u00e8 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 \u00e8 importante, sono indispensabili.<\/p>\n<h1>Coda a prova di guasto<\/h1>\n<p>\nQuando 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\u00f9 vecchio di ogni master e lo promuove come nuovo master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8d8227c00643f35e0dc752b6617e18fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 3. Diverse code mirrorate e le loro politiche<\/i><\/p>\n<p>Il broker 3 \u00e8 andato gi\u00f9. Si noti che lo specchio della coda C sul broker 2 \u00e8 stato elevato a master. Inoltre, \u00e8 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.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d08b3ada22e79686d448714f7bab009a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 4. Il broker 3 crolla, causando il fallimento della coda C<\/i> <\/p>\n<p>Il broker 1 sta cadendo! Ci rimane solo un broker. Lo specchio della coda B \u00e8 elevato a master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/dcc1d542c40c441194fd07e51046c619.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 5<\/i><\/p>\n<p>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. \u00c8 importante notare questo, poich\u00e9 avr\u00e0 delle conseguenze. Esamineremo presto queste conseguenze. Pertanto, il broker 1 \u00e8 ora di nuovo un membro del cluster, e il cluster cerca di rispettare le politiche e quindi crea specchi sul broker 1.<\/p>\n<p>In questo caso, la perdita del broker 1 \u00e8 stata totale, cos\u00ec come i dati, quindi la coda B non specchiata \u00e8 stata completamente persa.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/7ac7ab65ea6dff9c5a49372c04c83a37.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 6. Il broker 1 torna in funzione<\/i><\/p>\n<p>Il Broker 3 \u00e8 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 \u00e8 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\u00f9 avanti, poich\u00e9 prima dobbiamo considerare la sincronizzazione della coda. <\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/a54e53bb01e2f830a54f88acaa668984.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 7. Il Broker 3 torna online. Tutte le code principali su un singolo nodo!<\/i><\/p>\n<p>Cos\u00ec ora dovreste avere un'idea di come i mirror garantiscano ridondanza e tolleranza ai guasti. Ci\u00f2 assicura la disponibilit\u00e0 in caso di guasto di un nodo e protegge dalla perdita di dati. Ma non abbiamo ancora finito, perch\u00e9 in realt\u00e0 \u00e8 tutto molto pi\u00f9 complicato.<\/p>\n<h1>Sincronizzazione<\/h1>\n<p>\nQuando 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.<\/p>\n<p>Tale sincronizzazione pu\u00f2 essere eseguita automaticamente o manualmente e gestita tramite la politica delle code. Consideriamo un esempio.<\/p>\n<p>Abbiamo due code specchiate. La Coda A si sincronizza automaticamente, mentre la Coda B manualmente. In entrambe le code ci sono dieci messaggi.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/304f2a475fdd0cb6d3069140c667a0a7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 8. Due code con diversi modalit\u00e0 di sincronizzazione<\/i><\/p>\n<p>Ora stiamo perdendo il Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/49114966f440c407488bb467ff6dbf93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 9. Il Broker 3 \u00e8 andato offline<\/i><\/p>\n<p>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.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/adffc1f5eff8806edbd83772f338d67f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 10. Il nuovo specchio della Coda A riceve tutti i messaggi esistenti, mentre il nuovo specchio della Coda B no.<\/i><\/p>\n<p>Entrambe le code ricevono ulteriori dieci messaggi. Poi il Broker 2 si guasta, e la Coda A torna al suo specchio pi\u00f9 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\u00e9 questa coda non ha mai replicato i dieci messaggi originali.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c6cfef4bced5627bf243c2f020a42646.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 11. La Coda A torna al Broker 1 senza perdita di messaggi.<\/i><\/p>\n<p>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\u00e0 o la coerenza. <\/p>\n<p>Se vogliamo ottimizzare la disponibilit\u00e0, dobbiamo impostare la politica <b><i>ha-promote-on-failure<\/i><\/b> su <b><i>always<\/i><\/b>. Questo valore \u00e8 predefinito, quindi possiamo anche non specificare affatto la politica. In tal caso, sostanzialmente stiamo consentendo guasti negli specchi non sincronizzati. Questo porter\u00e0 alla perdita di messaggi, ma la coda rimane disponibile per la lettura e la scrittura.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/cd704cf4397184c212e1576b986abbaa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>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.<\/i><\/p>\n<p>Possiamo anche impostare <code>ha-promote-on-failure<\/code> su <code>when-synced<\/code>. In questo caso, invece di retrocedere su uno specchio, la coda attender\u00e0 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\u00e0 viene sacrificata per la sicurezza dei dati. Ma questo \u00e8 un modo rischioso, che potrebbe portare anche a una perdita totale di dati, su cui ci soffermeremo a breve.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/03fed936fe75220e22f68432ca81b654.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 13. La coda B rimane non disponibile dopo la perdita del Broker 1.<\/i><\/p>\n<p>Puoi farti la domanda: \u00abForse \u00e8 meglio non utilizzare mai la sincronizzazione automatica?\u00bb. La risposta \u00e8 che la sincronizzazione \u00e8 un'operazione bloccante. Durante la sincronizzazione, la coda principale non pu\u00f2 eseguire alcuna operazione di lettura o scrittura!<\/p>\n<p>Consideriamo un esempio. Attualmente abbiamo code molto lunghe. Come possono crescere a tale dimensione? Per diversi motivi:<\/p>\n<ul>\n<li>Le code non vengono utilizzate attivamente\n<\/li>\n<li>Si tratta di code ad alta velocit\u00e0, e in questo momento i consumatori stanno lavorando lentamente \n<\/li>\n<li>Si tratta di code ad alta velocit\u00e0, \u00e8 avvenuto un guasto e i consumatori stanno recuperando<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/dd4b0fd70cbbc0b7defc06536157770d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 14. Due grandi code con diverse modalit\u00e0 di sincronizzazione<\/i><\/p>\n<p>Ora si guasta il Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8c31cfdf485ab4c9dfe13e86a151df4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 15. Il Broker 3 si guasta, lasciando un master e uno specchio in ogni coda<\/i><\/p>\n<p>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 \u00e8 disponibile. La replica dei dati richiede due ore, il che porta a due ore di inattivit\u00e0 per questa Coda!<\/p>\n<p>Tuttavia, la Coda B rimane disponibile durante l'intero periodo. Ha sacrificato parte della ridondanza a favore della disponibilit\u00e0.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/28e641300a1c3f4d70e29a16db51521e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 16. La coda rimane non disponibile durante la sincronizzazione.<\/i><\/p>\n<p>Dopo due ore, anche la Coda A diventa disponibile e pu\u00f2 riprendere le operazioni di lettura e scrittura.<\/p>\n<h3>Aggiornamenti<\/h3>\n<p>\nQuesto 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\u00f2 significa che, non appena il broker torna, non perdiamo messaggi, l'unico danno subito \u00e8 stato solo l'arretrato della coda. Le regole di comportamento durante la disattivazione del broker sono definite dalla politica. <code>ha-promote-on-shutdown<\/code>. \u00c8 possibile impostare uno dei due valori:<\/p>\n<ul>\n<li><code>always<\/code>= attivato il passaggio a specchi non sincronizzati\n<\/li>\n<li><code>when-synced<\/code>= 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<\/li>\n<\/ul>\n<p>\nIn un modo o nell'altro, con code grandi si deve scegliere tra perdita di dati e indisponibilit\u00e0.<\/p>\n<h3>Quando la disponibilit\u00e0 aumenta la sicurezza dei dati<\/h3>\n<p>\nPrima di prendere una decisione, \u00e8 necessario considerare un'ulteriore complicazione. Anche se la sincronizzazione automatica \u00e8 migliore per la ridondanza, come influisce sulla sicurezza dei dati? Certamente, grazie a una maggiore ridondanza, RabbitMQ ha minori probabilit\u00e0 di perdere messaggi esistenti, ma che dire dei nuovi messaggi dai publisher?<\/p>\n<p>A questo proposito bisogna considerare:<\/p>\n<ul>\n<li>Pu\u00f2 un publisher semplicemente restituire un errore e un servizio superiore o un utente riprovare in seguito?\n<\/li>\n<li>Pu\u00f2 un publisher memorizzare un messaggio localmente o in un database per riprovare in seguito?<\/li>\n<\/ul>\n<p>\nSe il publisher pu\u00f2 soltanto scartare il messaggio, allora, in realt\u00e0, migliorare la disponibilit\u00e0 aumenta anche la sicurezza dei dati.<\/p>\n<p>Pertanto, bisogna cercare un equilibrio, e la soluzione dipende dalla situazione specifica.<\/p>\n<h1>Problemi con ha-promote-on-failure=when-synced<\/h1>\n<p>\nIdea <i><b>ha-promote-on-failure<\/b><\/i>= <i><b>when-synced<\/b><\/i> consiste nel prevenire il passaggio a uno specchio non sincronizzato, evitando cos\u00ec la perdita di dati. La coda rimane inaccessibile per lettura o scrittura. Invece, cerchiamo di ripristinare il broker arrestato con dati intatti, affinch\u00e9 possa riprendere operativit\u00e0 come master senza perdita di dati. <\/p>\n<p>Ma (e questo \u00e8 un grosso ma) se il broker ha perso i suoi dati, ci troviamo di fronte a un grande problema: la coda \u00e8 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.<\/p>\n<p>Per riaggiungere un nodo con lo stesso nome, diciamo al cluster di dimenticare il nodo perso (con il comando <i>rabbitmqctl forget_cluster_node<\/i>) e avviare un nuovo broker con lo stesso nome host. Finch\u00e9 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 \u00e8 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!<\/p>\n<p>Per questo motivo, la sincronizzazione manuale (e il mancato completamento della sincronizzazione) insieme a <code>ha-promote-on-failure=when-synced<\/code>, a mio avviso, \u00e8 piuttosto rischiosa. I documenti affermano che questa opzione esiste per la sicurezza dei dati, ma \u00e8 un doppio gioco.<\/p>\n<h1>Ribilanciamento dei master<\/h1>\n<p>\nCome promesso, torniamo al problema della concentrazione di tutti i master su uno o pi\u00f9 nodi. Questo pu\u00f2 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.<\/p>\n<p>Il ribilanciamento dei master pu\u00f2 essere problematica per due motivi:<\/p>\n<ul>\n<li>Non ci sono buoni strumenti per eseguire il ribilanciamento<\/li>\n<li>Sincronizzazione delle code<\/li>\n<\/ul>\n<p>\nPer il ribilanciamento c'\u00e8 un plugin di terze parti <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Ayanda-D\/rabbitmq-queue-master-balancer\">plugin<\/a><\/noindex>, che non \u00e8 supportato ufficialmente. Per quanto riguarda i plugin di terze parti, nel manuale di RabbitMQ <noindex><a rel=\"nofollow\" href=\"https:\/\/www.rabbitmq.com\/upgrade.html\">si dice<\/a><\/noindex>: \u00abIl plugin fornisce alcuni strumenti aggiuntivi per la configurazione e la reportistica, ma non \u00e8 supportato e non \u00e8 stato verificato dal team di RabbitMQ. Usalo a tuo rischio e pericolo\u00bb.<\/p>\n<p>C'\u00e8 anche un altro trucco per spostare la coda principale tramite politiche HA. Ne parla il manuale <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/rabbitmq\/support-tools\/blob\/master\/scripts\/rebalance-queue-masters\">script<\/a><\/noindex> per questo. Funziona come segue:<\/p>\n<ul>\n<li>Rimuove tutte le repliche utilizzando una politica temporanea con una priorit\u00e0 pi\u00f9 alta rispetto alla politica HA esistente.\n<\/li>\n<li>Modifica la politica temporanea HA per utilizzare la modalit\u00e0 \"nodi\" specificando il nodo su cui trasferire la coda principale.\n<\/li>\n<li>Sincronizza la coda per la migrazione forzata.\n<\/li>\n<li>Una volta completata la migrazione, rimuove la politica temporanea. La politica HA originale entra in vigore ed \u00e8 creata la quantit\u00e0 necessaria di repliche.<\/li>\n<\/ul>\n<p>\nLo svantaggio \u00e8 che questo approccio potrebbe non funzionare se hai code grandi o requisiti rigorosi di ridondanza.<\/p>\n<p>Ora vediamo come i cluster RabbitMQ funzionano con le partizioni di rete.<\/p>\n<h1>Violazione della connettivit\u00e0<\/h1>\n<p>\nI 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\u00e0 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\u00e0 e coerenza, e ancora una volta la buona notizia \u00e8 che RabbitMQ offre entrambe le opzioni (solo che non possono essere attive contemporaneamente).<\/p>\n<p>Con RabbitMQ abbiamo due opzioni principali:<\/p>\n<ul>\n<li>Consentire la divisione logica (split-brain). Questo garantisce la disponibilit\u00e0, ma pu\u00f2 provocare perdita di dati.\n<\/li>\n<li>Vietare la divisione logica. Pu\u00f2 portare a una perdita temporanea di disponibilit\u00e0 a seconda di come i client si connettono al cluster. Pu\u00f2 inoltre causare una completa indisponibilit\u00e0 in un cluster di due nodi.<\/li>\n<\/ul>\n<p>\nMa cos'\u00e8 la divisione logica? \u00c8 quando un cluster si divide a met\u00e0 a causa della perdita di collegamenti di rete. Su ciascun lato, i replica vengono promossi a master, quindi alla fine ogni coda ha pi\u00f9 master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d880a935df450fb994edfed0715e026e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>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.<\/i> <\/p>\n<p>Se i publisher inviano dati a entrambi i master, avremo due copie divergenti della coda.<\/p>\n<p>Le diverse modalit\u00e0 di RabbitMQ offrono o disponibilit\u00e0 o coerenza.<\/p>\n<h3>Modalit\u00e0 Ignora (predefinito)<\/h3>\n<p>\nQuesta modalit\u00e0 garantisce disponibilit\u00e0. Dopo una perdita di connettivit\u00e0, si verifica una divisione logica. Al ripristino della connettivit\u00e0, l'amministratore deve decidere quale sezione privilegiare. La parte perdente verr\u00e0 riavviata e tutti i dati accumulati su quel lato andranno persi.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/4d82c13b5ef21837ba819f5c246a1e41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 18. Tre publisher sono collegati a tre broker. Internamente, il cluster indirizza tutte le richieste alla coda principale sul Broker 2.<\/i><\/p>\n<p>Ora perdiamo il Broker 3. Vede che gli altri broker sono caduti e promuove il suo specchio a master. Cos\u00ec avviene la divisione logica.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c7e01d51b24023bacdd93cfad95c9eab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 19. Suddivisione logica (split-brain). Le registrazioni vanno in due principali code, e due copie si disperdono.<\/i><\/p>\n<p>La connettivit\u00e0 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.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/51c3ee15024d3c83ba625e3ff9cdeb90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 20. L'amministratore disconnette il Broker 3.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/0bac8e33de25c0c5381d336d26464858.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 21. L'amministratore riavvia il Broker 3, e si unisce al cluster, perdendo tutti i messaggi che erano presenti.<\/i><\/p>\n<p>Durante la perdita di connettivit\u00e0 e dopo il suo ripristino, il cluster e questa coda erano accessibili in lettura e scrittura.<\/p>\n<h3>Modalit\u00e0 Autoheal<\/h3>\n<p>\nFunziona in modo simile alla modalit\u00e0 Ignore, tranne per il fatto che il cluster stesso seleziona automaticamente il lato perdente dopo la suddivisione e il ripristino della connettivit\u00e0. Il lato perdente ritorna nel cluster vuoto, e la coda perde tutti i messaggi inviati solo a quel lato.<\/p>\n<h3>Modalit\u00e0 Pause Minority<\/h3>\n<p>\nSe non vogliamo causare una divisione logica, l'unica opzione \u00e8 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\u00e0, chiudendo tutte le connessioni esistenti e rifiutando eventuali nuove. Una volta al secondo controlla il ripristino della connettivit\u00e0. Non appena la connettivit\u00e0 \u00e8 ripristinata, riprende l'attivit\u00e0 e si riunisce al cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/7a51cf509b2c94e2ae100c7dedd9d21a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 22. Tre publisher sono collegati a tre broker. Internamente, il cluster dirige tutte le richieste nella coda principale sul Broker 2.<\/i><\/p>\n<p>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\u00e0 e diventa non disponibile.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c12ec38a47e1f8ccceebfa1854f54f21.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 23. Il Broker 3 sospende l'attivit\u00e0, disconnette tutti i clienti e rifiuta le richieste di connessione.<\/i><\/p>\n<p>Non appena la connettivit\u00e0 viene ripristinata, ritorna nel cluster.<\/p>\n<p>Vediamo un altro esempio, dove la coda principale si trova sul Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/4cc6a28270f00a280ecb5af5252f4e07.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 24. La coda principale \u00e8 sul Broker 3.<\/i><\/p>\n<p>Poi si verifica la stessa perdita di coerenza. Il Broker 3 va in pausa, poich\u00e9 si trova sul lato minore. Dall'altra parte, i nodi vedono che il Broker 3 \u00e8 caduto, quindi uno specchio pi\u00f9 vecchio dei Broker 1 e 2 viene elevato a master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d0d032385533bb53c5a95927afcd3119.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 25. Passaggio al Broker 2 in caso di indisponibilit\u00e0 del Broker 3.<\/i><\/p>\n<p>Quando la coerenza viene ripristinata, il Broker 3 si unir\u00e0 al cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/53f8186a040ae07724ef59cf79b72a0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 26. Il cluster \u00e8 tornato alla normale operativit\u00e0.<\/i><\/p>\n<p>\u00c8 importante capire qui che otteniamo coerenza, ma possiamo anche ottenere disponibilit\u00e0, <i><b>se<\/b><\/i> riusciamo a trasferire con successo i client sulla maggior parte della sezione. Per la maggior parte delle situazioni, personalmente sceglierei la modalit\u00e0 Pause Minority, ma questo dipende davvero dal caso specifico.<\/p>\n<p>Per garantire la disponibilit\u00e0, \u00e8 importante assicurarsi che i client si connettano con successo al nodo. Esaminiamo le nostre opzioni.<\/p>\n<h1>Assicurazione della coerenza dei client<\/h1>\n<p>\nAbbiamo diverse opzioni per reindirizzare i clienti alla parte principale del cluster o ai nodi operativi dopo la perdita di connettivit\u00e0 (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\u00e0 dove necessario. Tuttavia, quando un nodo \u00e8 in pausa, rifiuta le connessioni, quindi i clienti devono connettersi a un altro nodo. Se un nodo \u00e8 andato gi\u00f9, ha poco da fare.<\/p>\n<p>Le nostre opzioni:<\/p>\n<ul>\n<li>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 \u00e8 in pausa, i tentativi di connessione a quel nodo falliranno, ma i tentativi successivi verranno indirizzati ad altri server (in modalit\u00e0 ciclica). Questo \u00e8 adatto per una perdita di connettivit\u00e0 di breve durata o un server guasto che verr\u00e0 ripristinato rapidamente.\n<\/li>\n<li>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.\n<\/li>\n<li>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.\n<\/li>\n<li>Redirect traffic away from a dropped\/suspended node using DNS. This is accomplished with a low TTL.<\/li>\n<\/ul>\n<p><\/p>\n<h1>Conclusioni<\/h1>\n<p>\nRabbitMQ clustering has its advantages and disadvantages. The most significant drawbacks are that:<\/p>\n<ul>\n<li>when joining the cluster, nodes discard their data;\n<\/li>\n<li>blocking synchronization leads to queue unavailability.<\/li>\n<\/ul>\n<p>\nTutte 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\u00f9 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\u00e0. Non mi sentirei di raccomandare RabbitMQ con clustering nelle seguenti situazioni:<\/p>\n<ul>\n<li>Una rete non affidabile.\n<\/li>\n<li>Una memorizzazione non affidabile.\n<\/li>\n<li>Code molto grandi.<\/li>\n<\/ul>\n<p>\nPer quanto riguarda le impostazioni per l'alta disponibilit\u00e0, considera queste:<\/p>\n<ul>\n<li><code>ha-promote-on-failure=always<\/code>\n<\/li>\n<li><code>ha-sync-mode=manual<\/code>\n<\/li>\n<li><code>cluster_partition_handling=ignore<\/code> (o <code>autoheal<\/code>)\n<\/li>\n<li>messaggi persistenti\n<\/li>\n<li>assicurati che i client si connettano al nodo attivo quando un nodo si guasta<\/li>\n<\/ul>\n<p>\nPer la coerenza (sicurezza dei dati) considera le seguenti impostazioni:<\/p>\n<ul>\n<li>Publisher Confirms e Manual Acknowledgements sul lato del consumatore\n<\/li>\n<li><code>ha-promote-on-failure=when-synced<\/code>, se gli editori possono riprovare pi\u00f9 tardi e se hai uno storage molto affidabile! Altrimenti imposta <code>=always<\/code>.\n<\/li>\n<li><code>ha-sync-mode=automatic<\/code> (ma per code di inattivit\u00e0 superiori potrebbe essere necessario il modo manuale; inoltre, considera se l'inaccessibilit\u00e0 potrebbe comportare la perdita di messaggi)\n<\/li>\n<li>modalit\u00e0 Pausa Minoritaria\n<\/li>\n<li>messaggi persistenti<\/li>\n<\/ul>\n<p>\nNon abbiamo ancora affrontato tutte le questioni relative alla tolleranza ai guasti e all'alta disponibilit\u00e0; ad esempio, come eseguire in sicurezza procedure di amministrazione (come gli aggiornamenti progressivi). Dobbiamo parlare anche di federazione e del plugin Shovel.<\/p>\n<p>Se ho dimenticato qualcosa, per favore fammelo sapere.<\/p>\n<p>Vedi anche il mio <noindex><a rel=\"nofollow\" href=\"https:\/\/jack-vanlightly.com\/blog\/2018\/9\/10\/how-to-lose-messages-on-a-rabbitmq-cluster\">un post<\/a><\/noindex>, dove eseguo dei test nel cluster RabbitMQ utilizzando Docker e Blockade per verificare alcuni scenari di perdita di messaggi descritti in questo articolo.<\/p>\n<p>Articoli precedenti della serie: <br \/>\n\u21161 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/416629\/\">habr.com\/ru\/company\/itsumma\/blog\/416629<\/a><\/noindex> <br \/>\n\u21162 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/418389\/\">habr.com\/ru\/company\/itsumma\/blog\/418389<\/a><\/noindex> <br \/>\n\u21163 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/437446\/\">habr.com\/ru\/company\/itsumma\/blog\/437446<\/a><\/noindex><br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u2014 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0435\u043c\u044b, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0441\u0432\u044f\u0442\u0438\u043c RabbitMQ \u0438 Kafka \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438. \u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043e RabbitMQ, \u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u2014 \u043e Kafka, \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 RabbitMQ. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u043b\u0438\u043d\u043d\u0430\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043f\u043e\u0443\u0434\u043e\u0431\u043d\u0435\u0435. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438, \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 (HA), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0434\u0442\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438. RabbitMQ \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52525","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-09T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47RabbitMQ contro Kafka: affidabilit\u00e0 e alta disponibilit\u00e0 nei cluster | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-09T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52525","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:41:25","updated":"2026-01-24 03:54:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=52525"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52525\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=52525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=52525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=52525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}