RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat

В últim article vam analitzar el clustering de RabbitMQ per a la tolerància a errors i l'alta disponibilitat. Ara aprofundim en Apache Kafka.

Aquí la unitat de replicació és la partició. Cada tema té una o més seccions. Cada secció té un líder amb o sense seguidors. Quan creeu un tema, especifiqueu el nombre de particions i el coeficient de replicació. El valor habitual és 3, el que significa tres rèpliques: un líder i dos seguidors.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 1. Es distribueixen quatre seccions entre tres corredors

Totes les peticions de lectura i escriptura van al líder. Els seguidors envien periòdicament peticions al líder per rebre els missatges més recents. Els consumidors mai recorren als seguidors; aquests últims només existeixen per redundància i tolerància a errors.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat

Falla de partició

Quan un corredor falla, els líders de diverses seccions solen fallar. En cadascun d'ells, un seguidor d'un altre node es converteix en líder. De fet, no sempre és així, ja que el factor de sincronització també influeix: si hi ha seguidors sincronitzats, i si no, si es permet canviar a una rèplica no sincronitzada. Però de moment no ens compliquem les coses.

L'agent 3 abandona la xarxa i s'escull un nou líder per a la secció 2 a l'agent 2.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 2. El corredor 3 mor i el seu seguidor del corredor 2 és escollit com a nou líder de la partició 2

Aleshores l'agent 1 marxa i la secció 1 també perd el seu líder, el paper del qual passa a l'agent 2.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 3. Queda un corredor. Tots els líders estan en un corredor amb zero redundància

Quan el corredor 1 torna a estar en línia, afegeix quatre seguidors, proporcionant una mica de redundància a cada partició. Però tots els líders encara es van mantenir al corredor 2.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 4. Els líders romanen al corredor 2

Quan apareix el corredor 3, tornem a tres rèpliques per partició. Però tots els líders segueixen al corredor 2.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 5. Col·locació desequilibrada dels líders després de la restauració dels corredors 1 i 3

Kafka té una eina per a un millor reequilibri de líders que RabbitMQ. Allà, vau haver d'utilitzar un connector o un script de tercers que canviessin les polítiques per migrar el node mestre reduint la redundància durant la migració. A més, per a cues grans vam haver d'acceptar la indisponibilitat durant la sincronització.

Kafka té el concepte de "rèpliques preferides" per al paper de líder. Quan es creen particions de tema, Kafka intenta distribuir els líders de manera uniforme entre els nodes i marca aquests primers líders com a preferits. Amb el temps, a causa dels reinicis del servidor, errors i avaries de connectivitat, els líders poden acabar en altres nodes, com en el cas extrem descrit anteriorment.

Per solucionar-ho, Kafka ofereix dues opcions:

  • Opció auto.leader.rebalance.enable=true permet que el node controlador reassigni automàticament els líders a les rèpliques preferides i, per tant, restabliri la distribució uniforme.
  • L'administrador pot executar l'script kafka-preferred-replica-election.sh per a la reassignació manual.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 6. Rèpliques després del reequilibri

Aquesta va ser una versió simplificada del fracàs, però la realitat és més complexa, tot i que aquí no hi ha res massa complicat. Tot es redueix a rèpliques sincronitzades (Rèpliques In-Sync, ISR).

Rèpliques sincronitzades (ISR)

Un ISR és un conjunt de rèpliques d'una partició que es considera "sincronitzada" (en sincronització). Hi ha un líder, però potser no hi ha seguidors. Un seguidor es considera sincronitzat si ha fet còpies exactes de tots els missatges del líder abans que expiri l'interval rèplica.lag.time.max.ms.

Un seguidor s'elimina del conjunt ISR si:

  • no va fer una sol·licitud per seleccionar per a l'interval rèplica.lag.time.max.ms (presumptament mort)
  • no s'ha pogut actualitzar durant l'interval rèplica.lag.time.max.ms (considerat lent)

Els seguidors fan sol·licituds de mostreig a l'interval replica.fetch.wait.max.ms, que per defecte és de 500 ms.

Per explicar clarament el propòsit de l'ISR, hem de mirar les confirmacions del productor i alguns escenaris de fallada. Els productors poden triar quan el corredor envia la confirmació:

  • acks=0, la confirmació no s'envia
  • acks=1, la confirmació s'envia després que el líder hagi escrit un missatge al seu registre local
  • acks=all, la confirmació s'envia després que totes les rèpliques de l'ISR hagin escrit el missatge als registres locals

En terminologia de Kafka, si l'ISR ha desat un missatge, està "compromès". Acks=all és l'opció més segura, però també afegeix retard addicional. Vegem dos exemples de fracàs i com interactuen les diferents opcions "acks" amb el concepte ISR.

Acks=1 i ISR

En aquest exemple, veurem que si el líder no espera que es guardin tots els missatges de tots els seguidors, és possible la pèrdua de dades si el líder falla. La navegació a un seguidor no sincronitzat es pot activar o desactivar mitjançant la configuració habilitat.elecció.líder.impre.

En aquest exemple, el fabricant té el valor acks=1. La secció es distribueix entre els tres corredors. Broker 3 està enrere, es va sincronitzar amb el líder fa vuit segons i ara té 7456 missatges enrere. El corredor 1 només va quedar un segon darrere. El nostre productor envia un missatge i rep ràpidament una resposta, sense la sobrecàrrega de seguidors lents o morts que el líder no està esperant.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 7. ISR amb tres rèpliques

El corredor 2 falla i el productor rep un error de connexió. Després que el lideratge passi a l'agent 1, perdem 123 missatges. El seguidor del corredor 1 formava part de l'ISR, però no estava totalment sincronitzat amb el líder quan va caure.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 8. Els missatges es perden quan es bloqueja

En configuració bootstrap.servers El fabricant té diversos corredors a la llista i pot demanar a un altre corredor qui és el nou líder de la secció. A continuació, estableix una connexió amb l'agent 1 i continua enviant missatges.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 9. L'enviament de missatges es reprèn després d'una breu pausa

El corredor 3 està encara més enrere. Fa sol·licituds de recuperació però no es pot sincronitzar. Això pot ser degut a una connexió de xarxa lenta entre corredors, problema d'emmagatzematge, etc. S'elimina de l'ISR. Ara l'ISR consta d'una rèplica: el líder! El fabricant continua enviant missatges i rebent confirmacions.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 10. El seguidor del corredor 3 s'elimina de l'ISR

L'agent 1 baixa i el paper de lideratge passa a l'agent 3 amb la pèrdua de 15286 missatges! El fabricant rep un missatge d'error de connexió. La transició a un líder fora de l'ISR només va ser possible a causa de la configuració unclean.leader.election.enable=true. Si està instal·lat a false, aleshores la transició no es produiria i totes les sol·licituds de lectura i escriptura serien rebutjades. En aquest cas, esperem que el corredor 1 torni amb les seves dades intactes a la rèplica, que tornarà a prendre el lideratge.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 11. El corredor 1 cau. Quan es produeix un error, es perden un gran nombre de missatges

El productor estableix una connexió amb l'últim broker i veu que ara és el líder de la secció. Comença a enviar missatges al corredor 3.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 12. Després d'una breu pausa, els missatges s'envien de nou a la secció 0

Vam veure que, a part de breus interrupcions per establir noves connexions i buscar un nou líder, el fabricant enviava missatges constantment. Aquesta configuració garanteix la disponibilitat a costa de la coherència (seguretat de les dades). Kafka va perdre milers de missatges però va continuar acceptant nous escrits.

Acks=tots i ISR

Repetim aquest escenari de nou, però amb acks=tots. Broker 3 té una latència mitjana de quatre segons. El fabricant envia un missatge amb acks=tots, i ara no rep una resposta ràpida. El líder espera que el missatge sigui desat per totes les rèpliques de l'ISR.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 13. ISR amb tres rèpliques. Un és lent, el que provoca retards en la gravació

Després de quatre segons de retard addicional, el corredor 2 envia un ack. Totes les rèpliques estan completament actualitzades.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 14. Totes les rèpliques guarden missatges i envien un ack

El corredor 3 ara queda més enrere i s'elimina de l'ISR. La latència es redueix significativament perquè no queden rèpliques lentes a l'ISR. El corredor 2 ara només espera el corredor 1 i té un retard mitjà de 500 ms.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 15. La rèplica del corredor 3 s'elimina de l'ISR

Aleshores l'agent 2 cau i el lideratge passa a l'agent 1 sense perdre missatges.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 16. El corredor 2 cau

El fabricant troba un nou líder i comença a enviar-li missatges. La latència es redueix encara més perquè l'ISR consta ara d'una rèplica! Per tant l'opció acks=tots no afegeix redundància.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 17. La rèplica del corredor 1 pren el lideratge sense perdre missatges

Aleshores, l'agent 1 es bloqueja i el lideratge passa a l'agent 3 amb una pèrdua de 14238 missatges!

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 18. Mor el corredor 1 i la transició de lideratge amb un entorn no net provoca una pèrdua de dades important

No hem pogut instal·lar l'opció habilitat.elecció.líder.impre en sentit veritable. Per defecte és igual false. Configuració acks=tots с unclean.leader.election.enable=true proporciona accessibilitat amb una mica de seguretat de dades addicional. Però com podeu veure, encara podem perdre missatges.

Però, i si volem augmentar la seguretat de les dades? Pots posar unclean.leader.election.enable = fals, però això no ens protegirà necessàriament de la pèrdua de dades. Si el líder va caure amb força i s'emportava les dades, els missatges encara es perden i la disponibilitat es perd fins que l'administrador restableixi la situació.

És millor assegurar-se que tots els missatges són redundants i, en cas contrari, descartar la gravació. Aleshores, almenys des del punt de vista del corredor, la pèrdua de dades només és possible en cas de dues o més fallades simultànies.

Acks=all, min.insync.replicas i ISR

Amb configuració del tema min.insync.replicas Estem augmentant el nivell de seguretat de les dades. Repassem l'última part de l'escenari anterior, però aquesta vegada amb min.insync.replicas=2.

Així, el corredor 2 té un líder de rèplica i el seguidor del corredor 3 s'elimina de l'ISR.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 19. ISR a partir de dues rèpliques

El corredor 2 cau i el lideratge passa al corredor 1 sense perdre missatges. Però ara l'ISR només consta d'una rèplica. Això no compleix el nombre mínim per rebre registres i, per tant, el corredor respon a l'intent d'escriptura amb un error Not EnoughReplicas.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 20. El nombre d'ISR és un inferior al que s'especifica a min.insync.replicas

Aquesta configuració sacrifica la disponibilitat per la coherència. Abans de reconèixer un missatge, ens assegurem que estigui escrit en almenys dues rèpliques. Això dóna al fabricant molta més confiança. Aquí, la pèrdua de missatge només és possible si dues rèpliques fallen simultàniament en un interval curt fins que el missatge es replica a un seguidor addicional, cosa que és poc probable. Però si sou súper paranoic, podeu establir el factor de replicació a 5 i min.insync.replicas per 3. Aquí tres corredors han de caure al mateix temps per perdre el rècord! Per descomptat, pagueu per aquesta fiabilitat amb una latència addicional.

Quan l'accessibilitat és necessària per a la seguretat de les dades

Com a cas amb RabbitMQ, de vegades l'accessibilitat és necessària per a la seguretat de les dades. Aquí teniu el que heu de pensar:

  • Pot l'editor simplement retornar un error i fer que el servei o l'usuari avançat ho torni a provar més tard?
  • L'editor pot desar el missatge localment o a la base de dades per tornar-ho a provar més tard?

Si la resposta és no, aleshores optimitzar la disponibilitat millora la seguretat de les dades. Perdreu menys dades si trieu la disponibilitat en lloc de no gravar. Així, tot es redueix a trobar un equilibri, i la decisió depèn de la situació concreta.

El significat de ISR

La suite ISR us permet triar l'equilibri òptim entre la seguretat de les dades i la latència. Per exemple, garantir la disponibilitat en cas de fallada de la majoria de rèpliques, minimitzant l'impacte de les rèpliques mortes o lentes en termes de latència.

El significat el triem nosaltres mateixos rèplica.lag.time.max.ms segons les seves necessitats. Bàsicament, aquest paràmetre significa quant retard estem disposats a acceptar quan acks=tots. El valor predeterminat és de deu segons. Si us és massa llarg, podeu reduir-lo. Aleshores, la freqüència de canvis a l'ISR augmentarà, ja que els seguidors s'eliminaran i s'afegiran més sovint.

RabbitMQ és simplement un conjunt de miralls que cal replicar. Els miralls lents introdueixen una latència addicional i els miralls morts poden esperar fins que els paquets que comprovin la disponibilitat de cada node (marca neta) responguin. ISR és una manera interessant d'evitar aquests problemes de latència. Però correm el risc de perdre la redundància, ja que l'ISR només es pot reduir al líder. Per evitar aquest risc, utilitzeu la configuració min.insync.replicas.

Garantia de connexió del client

En configuració bootstrap.servers productor i consumidor poden especificar diversos corredors per connectar clients. La idea és que quan un node cau, en quedin diversos de recanvi amb els quals el client pot obrir una connexió. Aquests no són necessàriament caps de secció, sinó simplement un trampolí per a la càrrega inicial. El client els pot preguntar quin node allotja el líder de la partició de lectura/escriptura.

A RabbitMQ, els clients es poden connectar a qualsevol node i l'encaminament intern envia la sol·licitud a on ha d'anar. Això vol dir que podeu instal·lar un equilibrador de càrrega davant de RabbitMQ. Kafka requereix que els clients es connectin al node que allotja el líder de partició corresponent. En aquesta situació, no podeu instal·lar un equilibrador de càrrega. Llista bootstrap.servers És fonamental que els clients puguin accedir i trobar els nodes correctes després d'una fallada.

Arquitectura de consens de Kafka

Fins ara, no hem considerat com el clúster s'assabenta de la caiguda del corredor i com s'escull un nou líder. Per entendre com funciona Kafka amb particions de xarxa, primer heu d'entendre l'arquitectura de consens.

Cada clúster de Kafka es desplega juntament amb un clúster Zookeeper, que és un servei de consens distribuït que permet al sistema arribar a un consens sobre un estat determinat, prioritzant la coherència sobre la disponibilitat. Es requereix el consentiment de la majoria dels nodes Zookeeper per aprovar les operacions de lectura i escriptura.

Zookeeper emmagatzema l'estat del clúster:

  • Llista de temes, seccions, configuració, rèpliques líders actuals, rèpliques preferides.
  • Membres del clúster. Cada corredor fa un ping al clúster Zookeeper. Si no rep un ping en un període de temps especificat, Zookeeper registra el corredor com a no disponible.
  • Selecció dels nodes principals i de recanvi per al controlador.

El node controlador és un dels corredors de Kafka que s'encarrega d'elegir els líders de la rèplica. Zookeeper envia notificacions al controlador sobre la pertinença al clúster i els canvis de tema, i el controlador ha d'actuar amb aquests canvis.

Per exemple, prenem un tema nou amb deu particions i un factor de replicació de 3. El controlador ha d'escollir un líder per a cada partició, intentant distribuir de manera òptima els líders entre els corredors.

Per a cada controlador de secció:

  • actualitza la informació a Zookeeper sobre ISR i líder;
  • Envia un LeaderAndISRCommand a cada corredor que allotja una rèplica d'aquesta partició, informant els intermediaris sobre l'ISR i el líder.

Quan cau un corredor amb un líder, Zookeeper envia una notificació al controlador i tria un nou líder. De nou, el controlador primer actualitza Zookeeper i després envia una ordre a cada agent per notificar-los el canvi de lideratge.

Cada líder és responsable de reclutar els ISR. Configuració rèplica.lag.time.max.ms determina qui hi entrarà. Quan l'ISR canvia, el líder transmet informació nova a Zookeeper.

Zookeeper sempre està informat de qualsevol canvi perquè, en cas de fallada, la direcció passi sense problemes a un nou líder.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 21. Consens de Kafka

Protocol de replicació

Entendre els detalls de la replicació us ajuda a entendre millor els possibles escenaris de pèrdua de dades.

Consultes de mostreig, compensació final de registre (LEO) i marca d'aigua alta (HW)

Considerem que els seguidors envien periòdicament sol·licituds de recuperació al líder. L'interval predeterminat és de 500 ms. Això difereix de RabbitMQ perquè a RabbitMQ la replicació no l'inicia el mirall de la cua sinó el mestre. El mestre empeny els canvis als miralls.

El líder i tots els seguidors guarden l'etiqueta Log End Offset (LEO) i Highwater (HW). La marca LEO emmagatzema el desplaçament de l'últim missatge a la rèplica local i l'HW manté el desplaçament de l'últim commit. Recordeu que per a l'estat de confirmació, el missatge s'ha de mantenir a totes les rèpliques ISR. Això vol dir que LEO sol estar lleugerament per davant de HW.

Quan el líder rep un missatge, l'emmagatzema localment. El seguidor fa una sol·licitud de recuperació transmetent el seu LEO. Aleshores, el líder envia un lot de missatges a partir d'aquest LEO i també transmet el HW actual. Quan el líder rep informació que totes les rèpliques han emmagatzemat el missatge amb el desplaçament donat, mou la marca HW. Només el líder pot moure el HW, de manera que tots els seguidors coneixeran el valor actual de les respostes a la seva sol·licitud. Això vol dir que els seguidors poden quedar enrere del líder tant en missatge com en coneixement de HW. Els consumidors reben missatges només fins al HW actual.

Tingueu en compte que "persisteix" vol dir escrit a la memòria, no al disc. Per al rendiment, Kafka es sincronitza amb el disc a un interval específic. RabbitMQ també té aquest interval, però enviarà un reconeixement a l'editor només després que el mestre i tots els miralls hagin escrit el missatge al disc. Els desenvolupadors de Kafka, per raons de rendiment, van decidir enviar un ack tan bon punt el missatge s'escriu a la memòria. Kafka aposta que la redundància compensa el risc d'emmagatzemar breument missatges reconeguts només a la memòria.

Fracàs del líder

Quan un líder cau, Zookeeper ho notifica al controlador i selecciona una nova rèplica del líder. El nou líder estableix una nova marca HW segons el seu LEO. Aleshores, els seguidors reben informació sobre el nou líder. Depenent de la versió de Kafka, el seguidor triarà un dels dos escenaris següents:

  1. Truncarà el registre local a un HW conegut i enviarà una sol·licitud al nou líder per rebre missatges després d'aquesta marca.
  2. Enviarà una sol·licitud al líder per esbrinar el HW en el moment en què va ser elegit líder i després truncarà el registre a aquest desplaçament. Aleshores començarà a fer sol·licituds de recuperació periòdiques a partir d'aquest desplaçament.

És possible que un seguidor hagi de truncar el registre pels motius següents:

  • Quan un líder falla, el primer seguidor del conjunt ISR registrat amb Zookeeper guanya les eleccions i es converteix en el líder. És possible que tots els seguidors d'ISR, encara que es considerin "sincronitzats", no hagin rebut còpies de tots els missatges de l'antic líder. És totalment possible que el seguidor destacat no tingui la còpia més actualitzada. Kafka assegura que no hi ha divergència entre rèpliques. Així, per evitar discrepàncies, cada seguidor ha de truncar el seu registre al valor HW del nou líder en el moment de la seva elecció. Aquesta és una altra raó per la qual es configura acks=tots tan important per a la coherència.
  • Els missatges s'escriuen periòdicament al disc. Si tots els nodes del clúster fallen al mateix temps, les rèpliques amb diferents desplaçaments s'emmagatzemaran als discs. És possible que quan els corredors tornin a estar en línia, el nou líder que sigui elegit estigui darrere dels seus seguidors perquè es va guardar al disc abans que els altres.

Reunió amb el clúster

En tornar a unir-se al clúster, les rèpliques fan el mateix que quan falla un líder: comproven la rèplica del líder i trunquen el seu registre al seu HW (en el moment de l'elecció). En comparació, RabbitMQ tracta igualment els nodes reunits com a completament nous. En ambdós casos, el corredor descarta qualsevol estat existent. Si s'utilitza la sincronització automàtica, aleshores el mestre ha de replicar absolutament tot el contingut actual al nou mirall amb un mètode de "que tot el món espere". El mestre no accepta cap operació de lectura o escriptura durant aquesta operació. Aquest enfocament crea problemes en cues grans.

Kafka és un registre distribuït i, en general, emmagatzema més missatges que una cua RabbitMQ, on les dades s'eliminen de la cua després de llegir-les. Les cues actives haurien de romandre relativament petites. Però Kafka és un registre amb la seva pròpia política de retenció, que pot establir un període de dies o setmanes. L'enfocament de bloqueig de cua i sincronització completa és absolutament inacceptable per a un registre distribuït. En canvi, els seguidors de Kafka simplement trunquen el seu registre al HW del líder (en el moment de la seva elecció) si la seva còpia està per davant del líder. En el cas més probable, quan el seguidor està enrere, simplement comença a fer sol·licituds de recuperació a partir del seu LEO actual.

Els seguidors nous o que s'han unit comencen fora de l'ISR i no participen en les confirmacions. Simplement treballen al costat del grup, rebent missatges tan ràpidament com poden fins que es posen al dia amb el líder i entren a l'ISR. No hi ha cap bloqueig i no cal llençar totes les vostres dades.

Interrupció de la connectivitat

Kafka té més components que RabbitMQ, de manera que té un conjunt de comportaments més complex quan el clúster es desconnecta. Però Kafka es va dissenyar originalment per a clústers, de manera que les solucions estan molt ben pensades.

A continuació es mostren diversos escenaris d'error de connectivitat:

  • Escenari 1: el seguidor no veu el líder, però encara veu el Zookeeper.
  • Escenari 2: el líder no veu cap seguidor, però encara veu Zookeeper.
  • Escenari 3: el seguidor veu el líder, però no veu el Zookeeeper.
  • Escenari 4: el líder veu els seguidors, però no veu el Zookeeeper.
  • Escenari 5: el seguidor està completament separat dels altres nodes de Kafka i de Zookeeper.
  • Escenari 6: el líder està completament separat dels altres nodes de Kafka i de Zookeeper.
  • Escenari 7: el node del controlador Kafka no pot veure un altre node Kafka.
  • Escenari 8: el controlador Kafka no veu Zookeeper.

Cada escenari té el seu propi comportament.

Escenari 1: el seguidor no veu el líder, però encara veu Zookeeper

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 22. Escenari 1: ISR de tres rèpliques

La fallada de connectivitat separa l'agent 3 dels corredors 1 i 2, però no de Zookeeper. L'agent 3 ja no pot enviar sol·licituds de recuperació. Després d'haver passat el temps rèplica.lag.time.max.ms s'elimina de l'ISR i no participa en les confirmacions de missatges. Un cop es restableixi la connectivitat, reprendrà les sol·licituds de recuperació i s'unirà a l'ISR quan es posin al dia amb el líder. Zookeeper continuarà rebent pings i suposarà que el corredor està viu i bé.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 23. Escenari 1: el corredor s'elimina de l'ISR si no es rep cap sol·licitud de recuperació dins de l'interval replica.lag.time.max.ms

No hi ha cap suspensió de nodes ni de cervell dividit com a RabbitMQ. En canvi, es redueix la redundància.

Escenari 2: el líder no veu cap seguidor, però encara veu Zookeeper

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 24. Escenari 2. Líder i dos seguidors

Una interrupció de la connectivitat de xarxa separa el líder dels seguidors, però el corredor encara pot veure Zookeeper. Com en el primer escenari, l'ISR es redueix, però aquesta vegada només al líder, ja que tots els seguidors deixen d'enviar sol·licituds de recuperació. De nou, no hi ha divisió lògica. En canvi, hi ha una pèrdua de redundància per als missatges nous fins que es restableixi la connectivitat. Zookeeper continua rebent pings i creu que el corredor està viu i bé.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 25. Escenari 2. ISR s'ha reduït només al líder

Escenari 3. El seguidor veu el líder, però no veu el Zookeeeper

El seguidor està separat de Zookeeper, però no del corredor amb el líder. Com a resultat, el seguidor continua fent sol·licituds de recuperació i és membre de l'ISR. Zookeeper ja no rep pings i registra un xoc del corredor, però com que només és un seguidor, no hi ha conseqüències després de la recuperació.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 26. Escenari 3: el seguidor continua enviant sol·licituds de recuperació al líder

Escenari 4. El líder veu seguidors, però no veu Zookeeper

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 27. Escenari 4. Líder i dos seguidors

El líder està separat de Zookeeper, però no dels corredors amb seguidors.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 28. Escenari 4: líder aïllat de Zookeeper

Després d'un temps, Zookeeper registrarà un error del corredor i ho notificarà al controlador. Escollirà un nou líder entre els seus seguidors. Tanmateix, el líder original continuarà pensant que és el líder i continuarà acceptant entrades de acks=1. Els seguidors ja no li envien sol·licituds de recollida, de manera que les considerarà mortes i intentarà reduir l'ISR a si mateix. Però com que no té connexió amb Zookeeper, no podrà fer-ho i, en aquest moment, es negarà a acceptar més entrades.

Сообщения acks=tots no rebrà un reconeixement perquè l'ISR activa primer totes les rèpliques i els missatges no hi arriben. Quan el líder original intenti eliminar-los de l'ISR, no podrà fer-ho i deixarà d'acceptar cap missatge.

Els clients aviat noten el canvi de líder i comencen a enviar registres al nou servidor. Un cop restaurada la xarxa, el líder original veu que ja no és un líder i trunca el seu registre al valor HW que tenia el nou líder en el moment de la falla per evitar la divergència de registre. Aleshores començarà a enviar sol·licituds de recuperació al nou líder. Es perden tots els registres del líder original que no es reprodueixen al nou líder. És a dir, es perdran missatges que el líder original no va reconèixer en aquells segons en què dos líders treballaven.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 29. Escenari 4. El líder de l'agent 1 es converteix en un seguidor després de restaurar la xarxa

Escenari 5: el seguidor està completament separat dels altres nodes de Kafka i de Zookeeper

El seguidor està completament aïllat tant dels altres nodes de Kafka com de Zookeeper. Simplement s'elimina de l'ISR fins que la xarxa es restableixi, i després es posa al dia amb els altres.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 30. Escenari 5: el seguidor aïllat s'elimina de l'ISR

Escenari 6: el líder està completament separat dels altres nodes de Kafka i de Zookeeper

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 31. Escenari 6. Líder i dos seguidors

El líder està completament aïllat dels seus seguidors, el controlador i el Zookeeper. Durant un curt període continuarà acceptant entrades de acks=1.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 32. Escenari 6: aïllar el líder d'altres nodes Kafka i Zookeeper

No haver rebut sol·licituds després del venciment rèplica.lag.time.max.ms, intentarà reduir l'ISR a si mateix, però no ho podrà fer perquè no hi ha comunicació amb Zookeeper, llavors deixarà d'acceptar escriptures.

Mentrestant, Zookeeper marcarà el corredor aïllat com a mort i el controlador triarà un nou líder.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 33. Escenari 6. Dos líders

El líder original pot acceptar entrades durant uns segons, però després deixa d'acceptar cap missatge. Els clients s'actualitzen cada 60 segons amb les últimes metadades. Se'ls informarà del canvi de líder i començaran a enviar entrades al nou líder.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 34. Escenari 6: els fabricants canvien a un nou líder

Es perdran totes les entrades confirmades fetes pel líder original des de la pèrdua de connectivitat. Un cop restaurada la xarxa, el líder original descobrirà a través de Zookeeper que ja no és el líder. Aleshores truncarà el seu registre al HW del nou líder en el moment de les eleccions i començarà a enviar sol·licituds com a seguidor.

RabbitMQ vs Kafka: tolerància a fallades i alta disponibilitat
Arròs. 35. Escenari 6: el líder original es converteix en un seguidor després de restaurar la connectivitat de xarxa

En aquesta situació, la separació lògica es pot produir durant un període curt, però només si acks=1 и min.insync.replicas també 1. La separació lògica acaba automàticament després de restaurar la xarxa, quan el líder original s'adona que ja no és el líder, o quan tots els clients s'adonen que el líder ha canviat i comencen a escriure al nou líder, el que passi primer. En qualsevol cas, alguns missatges es perdran, però només amb acks=1.

Hi ha una altra variant d'aquest escenari on, just abans de la separació de la xarxa, els seguidors es van quedar enrere i el líder va comprimir l'ISR només a ell. Aleshores queda aïllat a causa de la pèrdua de connectivitat. S'escull un nou líder, però el líder original continua acceptant entrades, fins i tot acks=tots, perquè no hi ha ningú més a ISR excepte ell. Aquests registres es perdran un cop es recuperi la xarxa. L'única manera d'evitar aquesta opció és min.insync.replicas = 2.

Escenari 7: el node del controlador Kafka no pot veure un altre node Kafka

En general, un cop es perd la connexió amb un node Kafka, el controlador no podrà transmetre cap informació de canvi de líder. En el pitjor dels casos, això comportarà una separació lògica a curt termini, com en l'escenari 6. La majoria de les vegades, el corredor simplement no es convertirà en candidat al lideratge si aquest últim fracassa.

Escenari 8: el controlador Kafka no veu Zookeeper

Zookeeper no rebrà un ping del controlador caigut i seleccionarà un nou node Kafka com a controlador. El controlador original pot continuar presentant-se com a tal, però no rep notificacions de Zookeeper, de manera que no tindrà cap tasca per realitzar. Un cop restaurada la xarxa, s'adonarà que ja no és un controlador, sinó que s'ha convertit en un node Kafka normal.

Conclusions dels escenaris

Veiem que la pèrdua de connectivitat dels seguidors no provoca la pèrdua de missatges, sinó que simplement redueix temporalment la redundància fins que la xarxa es restableixi. Això, per descomptat, pot provocar la pèrdua de dades si es perden un o més nodes.

Si el líder es separa de Zookeeper a causa d'una pèrdua de connectivitat, això podria provocar que es perdin missatges de acks=1. La manca de comunicació amb Zookeeper provoca una breu separació lògica amb els dos líders. Aquest problema es resol amb el paràmetre acks=tots.

Paràmetre min.insync.replicas en dues o més rèpliques proporciona una seguretat addicional que aquests escenaris a curt termini no donaran lloc a missatges perduts com en l'escenari 6.

Resum dels missatges perduts

Enumerem totes les maneres en què podeu perdre dades a Kafka:

  • Qualsevol fallada del líder si els missatges es van confirmar utilitzant acks=1
  • Qualsevol transició bruta de lideratge, és a dir, a un seguidor fora de l'ISR, fins i tot amb acks=tots
  • Aïllar el líder de Zookeeper si es confirmaven els missatges acks=1
  • Aïllament complet del líder que ja ha reduït el grup ISR a si mateix. Tots els missatges es perdran, fins i tot acks=tots. Això només és cert si min.insync.replicas=1.
  • Falles simultànies de tots els nodes de partició. Com que els missatges es reconeixen des de la memòria, és possible que alguns encara no s'hagin escrit al disc. Després de reiniciar els servidors, és possible que faltin alguns missatges.

Les transicions de lideratge impures es poden evitar prohibint-les o assegurant almenys dos acomiadaments. La configuració més duradora és una combinació acks=tots и min.insync.replicas més de 1.

Comparació directa de la fiabilitat de RabbitMQ i Kafka

Per garantir la fiabilitat i l'alta disponibilitat, ambdues plataformes implementen un sistema de replicació primari i secundari. Tanmateix, RabbitMQ té un taló d'Aquil·les. Quan es tornen a connectar després d'un error, els nodes descarten les seves dades i es bloqueja la sincronització. Aquest doble cop qüestiona la longevitat de les grans cues a RabbitMQ. Haureu d'acceptar o bé una redundància reduïda o temps de bloqueig llargs. La reducció de la redundància augmenta el risc de pèrdua massiva de dades. Però si les cues són petites, per tal de redundància, es poden fer front a períodes curts d'indisponibilitat (uns quants segons) mitjançant intents de connexió repetits.

Kafka no té aquest problema. Descarta dades només des del punt de divergència entre el líder i el seguidor. Es guarden totes les dades compartides. A més, la replicació no bloqueja el sistema. El líder continua acceptant publicacions mentre el nou seguidor es posa al dia, de manera que per als devops, unir-se o tornar a unir-se al clúster es converteix en una tasca trivial. Per descomptat, encara hi ha problemes com l'amplada de banda de xarxa durant la rèplica. Si afegiu diversos seguidors al mateix temps, és possible que trobeu un límit d'ample de banda.

RabbitMQ és superior a Kafka en fiabilitat quan fallen diversos servidors d'un clúster al mateix temps. Com ja hem dit, RabbitMQ envia una confirmació a l'editor només després que el mestre i totes les rèpliques hagin escrit el missatge al disc. Però això afegeix una latència addicional per dos motius:

  • fsync cada pocs centenars de mil·lisegons
  • La fallada del mirall només es pot notar un cop ha expirat la vida útil dels paquets que comproven la disponibilitat de cada node (net tick). Si el mirall s'alenteix o cau, això afegeix un retard.

L'aposta de Kafka és que si un missatge s'emmagatzema en diversos nodes, pot reconèixer missatges tan bon punt arribin a la memòria. Per això, hi ha el risc de perdre missatges de qualsevol tipus (fins i tot acks=tots, min.insync.replicas=2) en cas de fallada simultània.

En general, Kafka presenta un millor rendiment del programari i està dissenyat des de zero per a clústers. El nombre de seguidors es pot augmentar a 11 si és necessari per a la fiabilitat. Factor de replicació 5 i nombre mínim de rèpliques en sincronització min.insync.replicas=3 farà que la pèrdua del missatge sigui un esdeveniment molt rar. Si la vostra infraestructura pot suportar aquesta proporció de replicació i nivell de redundància, podeu triar aquesta opció.

La agrupació en clúster RabbitMQ és bona per a cues petites. Però fins i tot les petites cues poden créixer ràpidament quan hi ha trànsit intens. Quan les cues siguin grans, haureu de prendre decisions difícils entre la disponibilitat i la fiabilitat. L'agrupament de RabbitMQ és el més adequat per a situacions no típiques en què els avantatges de la flexibilitat de RabbitMQ superen els desavantatges de la seva agrupació.

Un antídot a la vulnerabilitat de RabbitMQ a les cues grans és dividir-les en moltes cues més petites. Si no necessiteu una comanda completa de tota la cua, sinó només els missatges rellevants (per exemple, missatges d'un client específic) o no demaneu res, aleshores aquesta opció és acceptable: mira el meu projecte Reequilibrador per dividir la cua (el projecte encara està en una fase inicial).

Finalment, no us oblideu d'una sèrie d'errors en els mecanismes de clúster i replicació tant de RabbitMQ com de Kafka. Amb el pas del temps, els sistemes s'han tornat més madurs i estables, però cap missatge mai estarà 100% segur de la pèrdua! A més, es produeixen accidents a gran escala als centres de dades!

Si m'he perdut alguna cosa, m'he equivocat o no esteu d'acord amb algun dels punts, no dubteu a escriure un comentari o contactar amb mi.

Sovint em pregunten: "Què triar, Kafka o RabbitMQ?", "Quina plataforma és millor?". La veritat és que depèn molt de la teva situació, experiència actual, etc. Dubto a donar la meva opinió perquè seria massa simplificat recomanar una plataforma per a tots els casos d'ús i possibles limitacions. He escrit aquesta sèrie d'articles perquè us feu la vostra opinió.

Vull dir que tots dos sistemes són líders en aquest àmbit. Pot ser que estic una mica esbiaixat perquè, des de la meva experiència amb projectes, acostumo a valorar coses com l'ordre i la fiabilitat dels missatges garantits.

Veig altres tecnologies que no tenen aquesta fiabilitat i comandes garantides, després miro RabbitMQ i Kafka i m'adono del valor increïble d'aquests dos sistemes.

Font: www.habr.com

Afegeix comentari