RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade

В último artigo analizamos a agrupación de RabbitMQ para obter tolerancia a fallos e alta dispoñibilidade. Agora imos afondar en Apache Kafka.

Aquí a unidade de replicación é a partición. Cada tema ten unha ou máis seccións. Cada sección ten un líder con ou sen seguidores. Ao crear un tema, especifica o número de particións e o coeficiente de replicación. O valor habitual é 3, o que significa tres réplicas: un líder e dous seguidores.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 1. Catro seccións distribúense entre tres corredores

Todas as solicitudes de lectura e escritura van ao líder. Os seguidores envían periodicamente solicitudes ao líder para recibir as últimas mensaxes. Os consumidores nunca recorren aos seguidores; estes últimos só existen por redundancia e tolerancia a fallos.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade

Fallo de partición

Cando un corredor falla, os líderes de varias seccións adoitan fallar. En cada un deles, un seguidor doutro nodo convértese no líder. De feito, non sempre é así, xa que o factor de sincronización tamén inflúe: se hai seguidores sincronizados e, se non, se permite cambiar a unha réplica non sincronizada. Pero non nos compliquemos de momento.

O corredor 3 abandona a rede e elíxese un novo líder para a sección 2 no intermediario 2.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 2. O corredor 3 morre e o seu seguidor no corredor 2 é elixido como o novo líder da partición 2

Entón o corredor 1 sae e a sección 1 tamén perde o seu líder, cuxo papel pasa ao corredor 2.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 3. Queda un corredor. Todos os líderes están nun corredor con cero redundancia

Cando o corredor 1 volve estar en liña, engade catro seguidores, proporcionando certa redundancia a cada partición. Pero todos os líderes aínda permaneceron no corredor 2.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 4. Os líderes permanecen no corredor 2

Cando aparece o corredor 3, volvemos a tres réplicas por partición. Pero todos os líderes seguen no corredor 2.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 5. Colocación desequilibrada dos líderes tras a restauración dos corredores 1 e 3

Kafka ten unha ferramenta para un mellor reequilibrio de líderes que RabbitMQ. Alí, tivo que usar un complemento ou script de terceiros que cambiou as políticas para migrar o nodo mestre reducindo a redundancia durante a migración. Ademais, para colas grandes tivemos que aceptar a non dispoñibilidade durante a sincronización.

Kafka ten o concepto de "réplicas preferidas" para o papel de líder. Cando se crean particións de temas, Kafka tenta distribuír os líderes de xeito uniforme entre os nodos e marca os primeiros líderes como preferidos. Co paso do tempo, debido aos reinicios do servidor, fallos e avarías de conectividade, os líderes poden acabar noutros nodos, como no caso extremo descrito anteriormente.

Para solucionar isto, Kafka ofrece dúas opcións:

  • Opción auto.leader.rebalance.enable=verdadeiro permite que o nodo controlador reasigna automaticamente os líderes ás réplicas preferidas e restablece así a distribución uniforme.
  • O administrador pode executar o script kafka-preferred-replica-election.sh para reasignación manual.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 6. Réplicas despois do reequilibrio

Esta foi unha versión simplificada do fracaso, pero a realidade é máis complexa, aínda que aquí non hai nada demasiado complicado. Todo se reduce a réplicas sincronizadas (Réplicas en sincronización, ISR).

Réplicas sincronizadas (ISR)

Un ISR é un conxunto de réplicas dunha partición que se considera "sincronizada" (en sincronización). Hai un líder, pero pode que non haxa seguidores. Un seguidor considérase sincronizado se fixo copias exactas de todas as mensaxes do líder antes de que expire o intervalo réplica.lag.time.max.ms.

Elimínase un seguidor do conxunto ISR se:

  • non fixo unha solicitude para seleccionar para o intervalo réplica.lag.time.max.ms (presuntamente morto)
  • non conseguiu actualizar durante o intervalo réplica.lag.time.max.ms (considerado lento)

Os seguidores fan solicitudes de mostra no intervalo replica.fetch.wait.max.ms, que por defecto é 500 ms.

Para explicar claramente o propósito do ISR, necesitamos ver as confirmacións do produtor e algúns escenarios de fallo. Os produtores poden escoller cando o corredor envía a confirmación:

  • acks=0, non se envía a confirmación
  • acks=1, a confirmación envíase despois de que o líder escribiu unha mensaxe no seu rexistro local
  • acks=all, a confirmación envíase despois de que todas as réplicas do ISR escribiron a mensaxe nos rexistros locais

Na terminoloxía de Kafka, se o ISR gardou unha mensaxe, está "comprometida". Acks=all é a opción máis segura, pero tamén engade un atraso adicional. Vexamos dous exemplos de fracaso e como interactúan as diferentes opcións de 'acks' co concepto ISR.

Acks=1 e ISR

Neste exemplo, veremos que se o líder non espera a que todas as mensaxes de todos os seguidores sexan gardadas, entón é posible a perda de datos se o líder falla. A navegación a un seguidor non sincronizado pódese activar ou desactivar mediante a configuración inmundo.líder.elección.habilitar.

Neste exemplo, o fabricante ten o valor acks=1. A sección distribúese entre os tres corredores. Broker 3 está atrás, sincronizouse co líder hai oito segundos e agora está a 7456 mensaxes. O corredor 1 estaba só un segundo por detrás. O noso produtor envía unha mensaxe e recibe rapidamente un ack de volta, sen a sobrecarga de seguidores lentos ou mortos que o líder non está esperando.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 7. ISR con tres réplicas

O corredor 2 falla e o produtor recibe un erro de conexión. Despois de que o liderado pase ao corredor 1, perdemos 123 mensaxes. O seguidor do corredor 1 formaba parte do ISR, pero non estaba totalmente sincronizado co líder cando caeu.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 8. As mensaxes pérdense cando falla

En configuración bootstrap.servidores O fabricante ten varios corredores listados e pode preguntarlle a outro corretor quen é o novo líder da sección. A continuación, establece unha conexión co intermediario 1 e continúa enviando mensaxes.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 9. O envío de mensaxes retómase despois dunha pequena pausa

O corredor 3 está aínda máis atrás. Fai solicitudes de recuperación pero non se pode sincronizar. Isto pode deberse a unha conexión de rede lenta entre os corredores, a un problema de almacenamento, etc. Elimínase do ISR. Agora o ISR consiste nunha réplica: o líder! O fabricante segue enviando mensaxes e recibindo confirmacións.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 10. O seguidor do corredor 3 é eliminado do ISR

O corretor 1 cae e o papel de liderado pasa ao corredor 3 coa perda de 15286 mensaxes. O fabricante recibe unha mensaxe de erro de conexión. A transición a un líder fóra do ISR só foi posible debido á configuración unclean.leader.election.enable=verdadeiro. Se está instalado en teito, entón a transición non se produciría e todas as solicitudes de lectura e escritura serían rexeitadas. Neste caso, agardamos a que o corredor 1 volva cos seus datos intactos na réplica, que volverá asumir o liderado.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 11. Cae o corredor 1. Cando se produce un fallo, pérdese un gran número de mensaxes

O produtor establece unha conexión co último corredor e ve que agora é o líder da sección. Comeza a enviar mensaxes ao corredor 3.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 12. Despois dunha pequena pausa, as mensaxes envíanse de novo á sección 0

Vimos que, ademais de pequenas interrupcións para establecer novas conexións e buscar un novo líder, o fabricante enviaba mensaxes constantemente. Esta configuración garante a dispoñibilidade a costa da coherencia (seguridade dos datos). Kafka perdeu miles de mensaxes pero continuou aceptando novas escrituras.

Acks=todos e ISR

Repetimos este escenario de novo, pero con acks=todos. O corredor 3 ten unha latencia media de catro segundos. O fabricante envía unha mensaxe con acks=todos, e agora non recibe unha resposta rápida. O líder agarda a que todas as réplicas do ISR garde a mensaxe.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 13. ISR con tres réplicas. Un é lento, o que provoca atrasos na gravación

Despois de catro segundos de atraso adicional, o corredor 2 envía un ack. Todas as réplicas están agora totalmente actualizadas.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 14. Todas as réplicas gardan mensaxes e envían ack

O corredor 3 agora queda máis atrás e é eliminado do ISR. A latencia redúcese significativamente porque non quedan réplicas lentas no ISR. O corredor 2 agora só espera polo corredor 1 e ten un atraso medio de 500 ms.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 15. A réplica do corredor 3 elimínase do ISR

Entón o corredor 2 cae e o liderado pasa ao corredor 1 sen perda de mensaxes.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 16. Cae do corredor 2

O fabricante atopa un novo líder e comeza a enviarlle mensaxes. A latencia redúcese aínda máis porque o ISR agora consiste nunha réplica. Polo tanto a opción acks=todos non engade redundancia.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 17. A réplica do corredor 1 toma o liderado sen perder mensaxes

Entón, o corredor 1 falla e a vantaxe pasa ao corredor 3 cunha perda de 14238 mensaxes.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 18. O corredor 1 morre e a transición do liderado cunha configuración non limpa provoca unha gran perda de datos

Non puidemos instalar a opción inmundo.líder.elección.habilitar en significado certo. Por defecto é igual teito. Configuración acks=todos с unclean.leader.election.enable=verdadeiro ofrece accesibilidade con algunha seguridade de datos engadida. Pero como podes ver, aínda podemos perder mensaxes.

Pero e se queremos aumentar a seguridade dos datos? Podes poñer unclean.leader.election.enable = falso, pero isto non nos protexerá necesariamente da perda de datos. Se o líder caeu duro e levou os datos consigo, as mensaxes aínda se perden e a dispoñibilidade pérdese ata que o administrador restaure a situación.

É mellor asegurarse de que todas as mensaxes sexan redundantes e, en caso contrario, descartar a gravación. Entón, polo menos desde o punto de vista do corredor, a perda de datos só é posible no caso de dous ou máis fallos simultáneos.

Acks=todos, min.insync.replicas e ISR

Con configuración de tema min.insync.réplicas Estamos aumentando o nivel de seguridade dos datos. Repasemos de novo a última parte do escenario anterior, pero esta vez con min.insync.replicas=2.

Polo tanto, o corredor 2 ten un líder de réplica e o seguidor do corredor 3 é eliminado do ISR.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 19. ISR a partir de dúas réplicas

O corretor 2 cae e o liderado pasa ao corredor 1 sen perda de mensaxes. Pero agora o ISR consiste só nunha réplica. Isto non cumpre o número mínimo para recibir rexistros e, polo tanto, o corredor responde ao intento de escritura cun erro Non EnoughReplicas.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 20. O número de ISR é un inferior ao especificado en min.insync.replicas

Esta configuración sacrifica a dispoñibilidade para a coherencia. Antes de recoñecer unha mensaxe, asegurámonos de que está escrita en polo menos dúas réplicas. Isto dálle ao fabricante moita máis confianza. Aquí, a perda de mensaxes só é posible se dúas réplicas fallan simultáneamente nun intervalo curto ata que a mensaxe se replique a un seguidor adicional, o que é improbable. Pero se es super paranoico, podes establecer o factor de replicación en 5 e min.insync.réplicas por 3. Aquí tres corredores deben caer ao mesmo tempo para perder o récord! Por suposto, pagas por esta fiabilidade cunha latencia adicional.

Cando a accesibilidade sexa necesaria para a seguridade dos datos

Como dentro caso con RabbitMQ, ás veces a accesibilidade é necesaria para a seguridade dos datos. Aquí tes o que tes que pensar:

  • ¿Pode o editor simplemente devolver un erro e facer que o servizo ou usuario ascendente o intente de novo máis tarde?
  • Pode o editor gardar a mensaxe localmente ou nunha base de datos para tentalo de novo máis tarde?

Se a resposta é negativa, optimizar a dispoñibilidade mellora a seguridade dos datos. Perderás menos datos se escolles a dispoñibilidade en lugar de non gravar. Así, todo se reduce a atopar un equilibrio, e a decisión depende da situación concreta.

O significado de ISR

A suite ISR permítelle escoller o equilibrio óptimo entre a seguridade dos datos e a latencia. Por exemplo, garantir a dispoñibilidade en caso de falla da maioría das réplicas, minimizando o impacto das réplicas mortas ou lentas en canto á latencia.

Eliximos o significado nós mesmos réplica.lag.time.max.ms segundo as súas necesidades. Esencialmente, este parámetro significa canto atraso estamos dispostos a aceptar cando acks=todos. O valor predeterminado é de dez segundos. Se isto é demasiado longo para ti, podes reducilo. Entón, a frecuencia de cambios no ISR aumentará, xa que os seguidores serán eliminados e engadidos con máis frecuencia.

RabbitMQ é simplemente un conxunto de espellos que deben ser replicados. Os espellos lentos introducen unha latencia adicional e os espellos mortos poden esperar ata que os paquetes que comproban a dispoñibilidade de cada nodo (marca neta) respondan. ISR é unha forma interesante de evitar estes problemas de latencia. Pero corremos o risco de perder a redundancia xa que o ISR só pode encollerse ao líder. Para evitar este risco, use a configuración min.insync.réplicas.

Garantía de conexión do cliente

En configuración bootstrap.servidores produtor e consumidor poden especificar varios corredores para conectar clientes. A idea é que cando un nodo cae, queden varios de reposto cos que o cliente pode abrir unha conexión. Estes non son necesariamente líderes de sección, senón simplemente un trampolín para a carga inicial. O cliente pode preguntarlles que nodo alberga o líder da partición de lectura/escritura.

En RabbitMQ, os clientes poden conectarse a calquera nodo e o enrutamento interno envía a solicitude a onde precisa ir. Isto significa que pode instalar un equilibrador de carga fronte a RabbitMQ. Kafka require que os clientes se conecten ao nodo que aloxa o líder da partición correspondente. Nesta situación, non pode instalar un equilibrador de carga. Lista bootstrap.servidores É fundamental que os clientes poidan acceder e atopar os nodos correctos despois dun fallo.

Arquitectura de consenso de Kafka

Ata agora, non consideramos como o clúster aprende sobre a caída do corredor e como se elixe un novo líder. Para comprender como funciona Kafka coas particións de rede, primeiro cómpre comprender a arquitectura de consenso.

Cada clúster de Kafka está implantado xunto cun clúster Zookeeper, que é un servizo de consenso distribuído que permite que o sistema chegue a un consenso nalgún estado determinado, priorizando a coherencia sobre a dispoñibilidade. Requírese o consentimento da maioría dos nodos de Zookeeper para aprobar as operacións de lectura e escritura.

Zookeeper almacena o estado do clúster:

  • Lista de temas, seccións, configuración, réplicas líderes actuais, réplicas preferidas.
  • Membros do clúster. Cada corredor fai ping ao clúster Zookeeper. Se non recibe un ping nun período de tempo especificado, Zookeeper rexistra o corredor como non dispoñible.
  • Selección dos nodos principais e de reserva para o controlador.

O nodo controlador é un dos corredores de Kafka que se encarga de elixir os líderes de réplica. Zookeeper envía notificacións ao controlador sobre a pertenza ao clúster e os cambios de temas, e o controlador debe actuar sobre estes cambios.

Por exemplo, tomemos un novo tema con dez particións e un factor de replicación de 3. O controlador debe elixir un líder para cada partición, tentando distribuír de forma óptima os líderes entre os corredores.

Para cada controlador de sección:

  • actualiza información en Zookeeper sobre ISR e líder;
  • Envía un LeaderAndISRCommand a cada corredor que aloxa unha réplica desta partición, informando aos corredores sobre o ISR e o líder.

Cando cae un corredor cun líder, Zookeeper envía unha notificación ao controlador e elixe un novo líder. De novo, o controlador actualiza primeiro Zookeeper e despois envía un comando a cada corredor notificándolles o cambio de liderado.

Cada líder é responsable da contratación de ISR. Configuración réplica.lag.time.max.ms determina quen entrará alí. Cando o ISR cambia, o líder transmite nova información ao Zookeeper.

Zookeeper sempre está informado de calquera cambio, de xeito que, en caso de fallo, a xestión pasa sen problemas a un novo líder.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 21. Consenso de Kafka

Protocolo de replicación

Comprender os detalles da replicación axúdache a comprender mellor os posibles escenarios de perda de datos.

Consultas de mostraxe, compensación final de rexistro (LEO) e marca de auga alta (HW)

Consideramos que os seguidores envían periodicamente solicitudes de recuperación ao líder. O intervalo predeterminado é de 500 ms. Isto difire de RabbitMQ en que en RabbitMQ a replicación non é iniciada polo espello da cola senón polo mestre. O mestre empurra cambios nos espellos.

O líder e todos os seguidores gardan a etiqueta de compensación de final de rexistro (LEO) e a etiqueta Highwater (HW). A marca LEO almacena a compensación da última mensaxe na réplica local e o HW mantén a compensación da última confirmación. Lembra que para o estado de confirmación, a mensaxe debe ser persistente en todas as réplicas de ISR. Isto significa que LEO adoita estar lixeiramente por diante de HW.

Cando o líder recibe unha mensaxe, gárdaa localmente. O seguidor fai unha solicitude de recuperación transmitindo o seu LEO. A continuación, o líder envía un lote de mensaxes a partir deste LEO e tamén transmite o HW actual. Cando o líder recibe información de que todas as réplicas almacenaron a mensaxe no desfase indicado, move a marca HW. Só o líder pode mover o HW, polo que todos os seguidores coñecerán o valor actual nas respostas á súa solicitude. Isto significa que os seguidores poden quedar atrás do líder tanto en mensaxes como no coñecemento de HW. Os consumidores reciben mensaxes só ata o HW actual.

Teña en conta que "persiste" significa escrito na memoria, non no disco. Para o rendemento, Kafka sincroniza co disco nun intervalo específico. RabbitMQ tamén ten tal intervalo, pero enviará un recoñecemento ao editor só despois de que o mestre e todos os espellos escribiran a mensaxe no disco. Os desenvolvedores de Kafka, por razóns de rendemento, decidiron enviar un ack en canto a mensaxe se escriba na memoria. Kafka aposta por que a redundancia compensa o risco de almacenar brevemente as mensaxes recoñecidas só na memoria.

Fracaso do líder

Cando un líder cae, Zookeeper avisa ao controlador e selecciona unha nova réplica do líder. O novo líder establece unha nova marca HW segundo o seu LEO. Os seguidores reciben entón información sobre o novo líder. Dependendo da versión de Kafka, o seguidor escollerá un dos dous escenarios:

  1. Truncará o rexistro local a un HW coñecido e enviará unha solicitude ao novo líder para recibir mensaxes despois desta marca.
  2. Enviará unha solicitude ao líder para descubrir o HW no momento en que foi elixido líder e logo truncará o rexistro a esta compensación. Despois comezará a facer solicitudes de recuperación periódicas a partir desta compensación.

Un seguidor pode ter que truncar o rexistro polos seguintes motivos:

  • Cando un líder falla, o primeiro seguidor do conxunto ISR rexistrado en Zookeeper gaña as eleccións e convértese no líder. Todos os seguidores de ISR, aínda que se consideran "sincronizados", poden non recibir copias de todas as mensaxes do antigo líder. É totalmente posible que o seguidor destacado non teña a copia máis actualizada. Kafka asegura que non haxa diverxencia entre as réplicas. Así, para evitar discrepancias, cada seguidor debe truncar o seu rexistro ao valor HW do novo líder no momento da súa elección. Esta é outra razón pola que se configura acks=todos tan importante para a coherencia.
  • As mensaxes escríbense periodicamente no disco. Se todos os nodos do clúster fallan ao mesmo tempo, almacenaranse nos discos as réplicas con diferentes compensacións. É posible que cando os corredores volvan estar en liña, o novo líder que sexa elixido estea detrás dos seus seguidores porque foi gardado no disco antes que os demais.

Reencontro co clúster

Ao reincorporarse ao clúster, as réplicas fan o mesmo que cando falla un líder: comproban a réplica do líder e truncan o seu rexistro ao seu HW (no momento da elección). En comparación, RabbitMQ trata igualmente os nodos reunidos como completamente novos. En ambos os casos, o corredor descarta calquera estado existente. Se se usa a sincronización automática, entón o mestre debe replicar absolutamente todo o contido actual no novo espello nun método "deixa que todo o mundo espere". O mestre non acepta operacións de lectura ou escritura durante esta operación. Este enfoque crea problemas en grandes colas.

Kafka é un rexistro distribuído e, en xeral, almacena máis mensaxes que unha cola RabbitMQ, onde os datos son eliminados da cola despois de ser lidos. As colas activas deben permanecer relativamente pequenas. Pero Kafka é un rexistro cunha política de retención propia, que pode establecer un período de días ou semanas. O enfoque de bloqueo de filas e sincronización total é absolutamente inaceptable para un rexistro distribuído. Pola contra, os seguidores de Kafka simplemente truncan o seu rexistro no HW do líder (no momento da súa elección) se a súa copia está por diante do líder. No caso máis probable, cando o seguidor está detrás, simplemente comeza a facer solicitudes de recuperación comezando polo seu LEO actual.

Os seguidores novos ou unidos comezan fóra do ISR e non participan nos commits. Simplemente traballan xunto co grupo, recibindo mensaxes o máis rápido posible ata que se atopan ao día co líder e entran no ISR. Non hai bloqueo nin é necesario tirar todos os seus datos.

Perda de conectividade

Kafka ten máis compoñentes que RabbitMQ, polo que ten un conxunto máis complexo de comportamentos cando o clúster se desconecta. Pero Kafka foi deseñado orixinalmente para clusters, polo que as solucións están moi ben pensadas.

A continuación móstranse varios escenarios de falla de conectividade:

  • Escenario 1: o seguidor non ve o líder, pero aínda así o ve ao Zookeeper.
  • Escenario 2: o líder non ve seguidores, pero aínda así ve a Zookeeper.
  • Escenario 3: o seguidor ve ao líder, pero non ao Zookeeper.
  • Escenario 4: o líder ve aos seguidores, pero non ve ao Zookeeper.
  • Escenario 5: o seguidor está completamente separado dos outros nodos de Kafka e de Zookeeper.
  • Escenario 6: o líder está completamente separado dos outros nodos de Kafka e do Zookeeper.
  • Escenario 7: o nodo controlador Kafka non pode ver outro nodo Kafka.
  • Escenario 8: o controlador Kafka non ve Zookeeper.

Cada escenario ten o seu propio comportamento.

Escenario 1: o seguidor non ve ao líder, pero aínda así ve ao Zookeeper

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 22. Escenario 1: ISR de tres réplicas

A falla de conectividade separa o corredor 3 dos corredores 1 e 2, pero non de Zookeeper. O corredor 3 xa non pode enviar solicitudes de recuperación. Despois de que pasou o tempo réplica.lag.time.max.ms elimínase do ISR e non participa nas confirmacións de mensaxes. Unha vez que se restableza a conectividade, retomará as solicitudes de recuperación e unirase ao ISR cando se poña ao día co líder. Zookeeper seguirá recibindo pings e asumirá que o corredor está vivo e ben.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 23. Escenario 1: o corredor elimínase do ISR se non se recibe ningunha solicitude de obtención do mesmo dentro do intervalo replica.lag.time.max.ms

Non hai suspensión de nodos nin de cerebro dividido como en RabbitMQ. Pola contra, redúcese a redundancia.

Escenario 2: o líder non ve seguidores, pero aínda así ve a Zookeeper

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 24. Escenario 2. Líder e dous seguidores

Unha avaría na conectividade da rede separa o líder dos seguidores, pero o corredor aínda pode ver a Zookeeper. Como no primeiro escenario, o ISR diminúe, pero esta vez só para o líder xa que todos os seguidores deixan de enviar solicitudes de recuperación. De novo, non hai división lóxica. Pola contra, hai unha perda de redundancia para as novas mensaxes ata que se restableza a conectividade. Zookeeper segue recibindo pings e cre que o corredor está vivo e ben.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 25. Escenario 2. ISR reduciuse só ao líder

Escenario 3. O seguidor ve ao líder, pero non ao Zookeeper

O seguidor está separado de Zookeeper, pero non do corredor co líder. Como resultado, o seguidor segue facendo solicitudes de recuperación e sendo membro do ISR. Zookeeper xa non recibe pings e rexistra un accidente do corredor, pero como só é un seguidor, non hai consecuencias despois da recuperación.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 26. Escenario 3: o seguidor segue enviando solicitudes de recuperación ao líder

Escenario 4. O líder ve seguidores, pero non ve a Zookeeper

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 27. Escenario 4. Líder e dous seguidores

O líder está separado de Zookeeper, pero non dos corredores con seguidores.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 28. Escenario 4: líder illado de Zookeeper

Despois dun tempo, Zookeeper rexistrará un fallo do corredor e notificará ao controlador sobre iso. Elixirá un novo líder entre os seus seguidores. Non obstante, o líder orixinal seguirá pensando que é o líder e seguirá aceptando entradas de acos = 1. Os seguidores xa non lle envían solicitudes de obtención, polo que considerará mortos e tentará reducir o ISR a si mesmo. Pero como non ten conexión con Zookeeper, non poderá facelo e, nese momento, rexeitará aceptar máis entradas.

Сообщения acks=todos non recibirá un acuse de recibo porque o ISR activa primeiro todas as réplicas e as mensaxes non chegan a elas. Cando o líder orixinal intente eliminalos do ISR, non poderá facelo e deixará de aceptar ningunha mensaxe.

Os clientes pronto notan o cambio de líder e comezan a enviar rexistros ao novo servidor. Unha vez restaurada a rede, o líder orixinal ve que xa non é un líder e trunca o seu rexistro ao valor HW que tiña o novo líder no momento da falla para evitar a diverxencia de rexistro. Despois comezará a enviar solicitudes de recuperación ao novo líder. Todos os rexistros do líder orixinal que non se replican ao novo líder pérdense. É dicir, perderanse mensaxes que non foron recoñecidas polo líder orixinal neses poucos segundos nos que traballaban dous líderes.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 29. Escenario 4. O líder do corredor 1 convértese en seguidor despois de que se restableza a rede

Escenario 5: o seguidor está completamente separado dos outros nodos de Kafka e de Zookeeper

O seguidor está completamente illado tanto doutros nodos de Kafka como de Zookeeper. Simplemente elimínase do ISR ata que se restaure a rede e, a continuación, ponse ao día cos demais.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 30. Escenario 5: elimínase o seguidor illado do ISR

Escenario 6: o líder está completamente separado dos outros nodos de Kafka e do Zookeeper

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 31. Escenario 6. Líder e dous seguidores

O líder está completamente illado dos seus seguidores, o controlador e o Zookeeper. Durante un breve período seguirá aceptando entradas de acos = 1.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 32. Escenario 6: Illar o líder doutros nodos Kafka e Zookeeper

Non ter recibido solicitudes despois do vencemento réplica.lag.time.max.ms, intentará reducir o ISR a si mesmo, pero non poderá facelo porque non hai comunicación con Zookeeper, entón deixará de aceptar escrituras.

Mentres tanto, Zookeeper marcará o corredor illado como morto e o controlador elixirá un novo líder.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 33. Escenario 6. Dous líderes

O líder orixinal pode aceptar entradas durante uns segundos, pero despois deixa de aceptar mensaxes. Os clientes actualízanse cada 60 segundos cos últimos metadatos. Serán informados do cambio de líder e comezarán a enviar entradas ao novo líder.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 34. Escenario 6: os fabricantes cambian a un novo líder

Todas as entradas confirmadas realizadas polo líder orixinal desde a perda de conectividade perderanse. Unha vez restaurada a rede, o líder orixinal descubrirá a través de Zookeeper que xa non é o líder. Logo truncará o seu rexistro no HW do novo líder no momento da elección e comezará a enviar solicitudes como seguidor.

RabbitMQ vs Kafka: tolerancia a fallos e alta dispoñibilidade
Arroz. 35. Escenario 6: o líder orixinal convértese nun seguidor despois de restablecer a conectividade da rede

Nesta situación, a separación lóxica pode ocorrer durante un período curto, pero só se acos = 1 и min.insync.réplicas tamén 1. A separación lóxica remata automaticamente despois de restaurar a rede, cando o líder orixinal dáse conta de que xa non é o líder ou cando todos os clientes se dan conta de que o líder cambiou e comezan a escribirlle ao novo líder, o que suceda primeiro. En calquera caso, algunhas mensaxes perderanse, pero só con acos = 1.

Hai outra variante deste escenario onde, xusto antes da división da rede, os seguidores quedaron atrás e o líder comprimiu o ISR só para si mesmo. Despois queda illado debido á perda de conectividade. Elíxese un novo líder, pero o líder orixinal segue aceptando entradas, incluso acks=todos, porque non hai ninguén máis en ISR excepto el. Estes rexistros perderanse unha vez que se restaure a rede. O único xeito de evitar esta opción é min.insync.replicas = 2.

Escenario 7: o nodo controlador Kafka non pode ver outro nodo Kafka

En xeral, unha vez que se perda a conexión cun nodo Kafka, o controlador non poderá transmitirlle ningunha información de cambio de líder. No peor dos casos, isto levará a unha separación lóxica a curto prazo, como no escenario 6. Na maioría das veces, o corredor simplemente non se converterá nun candidato ao liderado se este último falla.

Escenario 8: o controlador Kafka non ve Zookeeper

Zookeeper non recibirá un ping do controlador caído e seleccionará un novo nodo Kafka como controlador. O controlador orixinal pode seguir presentándose como tal, pero non recibe notificacións de Zookeeper, polo que non terá tarefas que realizar. Unha vez que se restaure a rede, entenderase que xa non é un controlador, senón que se converteu nun nodo Kafka normal.

Conclusións dos escenarios

Vemos que a perda da conectividade dos seguidores non provoca a perda de mensaxes, senón que simplemente reduce temporalmente a redundancia ata que se restaure a rede. Isto, por suposto, pode levar á perda de datos se se perden un ou máis nodos.

Se o líder se separa de Zookeeper debido a unha perda de conectividade, isto pode provocar que se perdan mensaxes de acos = 1. A falta de comunicación con Zookeeper provoca unha breve división lóxica cos dous líderes. Este problema resólvese co parámetro acks=todos.

Parámetro min.insync.réplicas en dúas ou máis réplicas ofrece unha garantía adicional de que tales escenarios a curto prazo non provocarán mensaxes perdidas como no escenario 6.

Resumo de mensaxes perdidas

Imos enumerar todas as formas en que pode perder datos en Kafka:

  • Calquera fallo do líder se as mensaxes foron confirmadas usando acos = 1
  • Calquera transición impura de liderado, é dicir, a un seguidor fóra do ISR, mesmo con acks=todos
  • Illando o líder de Zookeeper se as mensaxes foron confirmadas usando acos = 1
  • Illamento total do líder que xa reduciu o grupo ISR a si mesmo. Todas as mensaxes perderanse, incluso acks=todos. Isto só é certo se min.insync.replicas=1.
  • Fallos simultáneos de todos os nodos de partición. Dado que as mensaxes se recoñecen desde a memoria, é posible que algunhas aínda non estean escritas no disco. Despois de reiniciar os servidores, é posible que falten algunhas mensaxes.

As transicións de liderado impuras pódense evitar prohibíndoas ou asegurando polo menos dous despedimentos. A configuración máis duradeira é unha combinación acks=todos и min.insync.réplicas máis de 1.

Comparación directa da fiabilidade de RabbitMQ e Kafka

Para garantir a fiabilidade e alta dispoñibilidade, ambas as plataformas implementan un sistema de replicación primario e secundario. Non obstante, RabbitMQ ten un talón de Aquiles. Cando se reconectan despois dun fallo, os nodos descartan os seus datos e bloquearase a sincronización. Este dobre golpe pon en dúbida a lonxevidade das grandes colas en RabbitMQ. Terás que aceptar unha redundancia reducida ou tempos de bloqueo longos. Reducir a redundancia aumenta o risco de perda masiva de datos. Pero se as colas son pequenas, entón, en aras da redundancia, pódense xestionar períodos curtos de indisponibilidade (uns segundos) mediante intentos de conexión repetidos.

Kafka non ten este problema. Descarta datos só dende o punto de diverxencia entre o líder e o seguidor. Todos os datos compartidos gárdanse. Ademais, a replicación non bloquea o sistema. O líder segue aceptando publicacións mentres o novo seguidor se pon ao día, polo que para os devops, unirse ou unirse ao clúster convértese nunha tarefa trivial. Por suposto, aínda hai problemas como o ancho de banda da rede durante a replicación. Se engades varios seguidores ao mesmo tempo, podes atopar un límite de ancho de banda.

RabbitMQ é superior a Kafka en fiabilidade cando fallan varios servidores nun clúster ao mesmo tempo. Como xa dixemos, RabbitMQ envía unha confirmación ao editor só despois de que o mestre e todos os espellos escriban a mensaxe no disco. Pero isto engade unha latencia adicional por dúas razóns:

  • fsync cada poucos centos de milisegundos
  • O fallo do espello só se pode notar despois de que caduque a vida útil dos paquetes que comproban a dispoñibilidade de cada nodo (net tick). Se o espello ralentiza ou cae, isto engade un atraso.

A aposta de Kafka é que, se unha mensaxe se almacena en varios nodos, pode recoñecer as mensaxes en canto chegan á memoria. Debido a isto, existe o risco de perder mensaxes de calquera tipo (incluso acks=todos, min.insync.replicas=2) en caso de fallo simultáneo.

En xeral, Kafka presenta un mellor rendemento do software e está deseñado desde cero para clusters. O número de seguidores pódese aumentar a 11 se é necesario para a fiabilidade. Factor de replicación 5 e número mínimo de réplicas en sincronización min.insync.replicas=3 fará que a perda de mensaxes sexa un evento moi raro. Se a túa infraestrutura pode soportar esta proporción de replicación e o nivel de redundancia, podes escoller esta opción.

A agrupación RabbitMQ é boa para pequenas colas. Pero incluso as pequenas colas poden crecer rapidamente cando hai tráfico intenso. Unha vez que as colas sexan grandes, terás que facer eleccións difíciles entre a dispoñibilidade e a fiabilidade. A agrupación de RabbitMQ é máis adecuada para situacións non típicas nas que os beneficios da flexibilidade de RabbitMQ superan as desvantaxes da súa agrupación.

Un antídoto para a vulnerabilidade de RabbitMQ ás grandes filas é dividilas en moitas filas máis pequenas. Se non precisa o pedido completo de toda a cola, senón só as mensaxes relevantes (por exemplo, mensaxes dun cliente específico) ou non solicita nada, entón esta opción é aceptable: mira o meu proxecto Reequilibrador para dividir a cola (o proxecto aínda está nunha fase inicial).

Finalmente, non te esquezas dunha serie de erros nos mecanismos de agrupación e replicación de RabbitMQ e Kafka. Co paso do tempo, os sistemas fixéronse máis maduros e estables, pero ningunha mensaxe estará 100 % a salvo da perda. Ademais, ocorren accidentes a gran escala nos centros de datos!

Se perdín algo, cometín un erro ou non estás de acordo con algún dos puntos, non dubides en escribir un comentario ou contactar comigo.

Moitas veces me preguntan: "Que escoller, Kafka ou RabbitMQ?", "Que plataforma é mellor?". A verdade é que depende moito da túa situación, experiencia actual, etc. Dubido en dar a miña opinión porque sería demasiado simplificado recomendar unha plataforma para todos os casos de uso e posibles limitacións. Escribín esta serie de artigos para que poidas formar a túa propia opinión.

Quero dicir que ambos os sistemas son líderes neste ámbito. Pode ser un pouco parcial porque pola miña experiencia con proxectos adoito valorar cousas como a orde e a fiabilidade das mensaxes garantidas.

Vexo outras tecnoloxías que carecen desta fiabilidade e pedidos garantidos, entón miro RabbitMQ e Kafka e decátome do incrible valor destes dous sistemas.

Fonte: www.habr.com

Engadir un comentario