{"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\/pt\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","title":{"rendered":"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/d8e584d210a6a016a962ad6f956a2078.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA resili\u00eancia e alta disponibilidade s\u00e3o grandes t\u00f3picos, ent\u00e3o dedicaremos artigos separados ao RabbitMQ e ao Kafka. Este artigo \u00e9 sobre o RabbitMQ, e o pr\u00f3ximo ser\u00e1 sobre o Kafka, em compara\u00e7\u00e3o com o RabbitMQ. O artigo \u00e9 longo, ent\u00e3o acomode-se confortavelmente.<\/p>\n<p>Vamos considerar as estrat\u00e9gias de resili\u00eancia, consist\u00eancia e alta disponibilidade (HA), assim como os compromissos que devem ser feitos em cada estrat\u00e9gia. O RabbitMQ pode operar em um cluster de n\u00f3s \u2014 e, nesse caso, \u00e9 classificado como um sistema distribu\u00eddo. Quando falamos de sistemas distribu\u00eddos, frequentemente tratamos de consist\u00eancia e disponibilidade. <\/p>\n<p>Esses conceitos descrevem como um sistema se comporta durante uma falha. Falha de conex\u00e3o de rede, falha de servidor, falha de disco r\u00edgido, indisponibilidade tempor\u00e1ria do servidor devido a coleta de lixo, perda de pacotes ou lentid\u00e3o na conex\u00e3o de rede. Tudo isso pode causar perda de dados ou conflitos. Aparentemente, \u00e9 praticamente imposs\u00edvel manter um sistema que seja simultaneamente e totalmente consistente (sem perda de dados, sem diverg\u00eancias) e dispon\u00edvel (que aceite opera\u00e7\u00f5es de leitura e grava\u00e7\u00e3o) para todas as poss\u00edveis falhas.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nVeremos que consist\u00eancia e disponibilidade est\u00e3o em extremos opostos do espectro, e voc\u00ea precisa escolher para que lado otimizar. A boa not\u00edcia \u00e9 que, com o RabbitMQ, essa escolha \u00e9 poss\u00edvel. Voc\u00ea tem essas 'alavancas de nerd' para deslocar o equil\u00edbrio em dire\u00e7\u00e3o a maior consist\u00eancia ou maior disponibilidade.<\/p>\n<p>Vamos prestar aten\u00e7\u00e3o especial \u00e0s configura\u00e7\u00f5es que podem levar \u00e0 perda de dados devido a confirma\u00e7\u00f5es de grava\u00e7\u00e3o. H\u00e1 uma cadeia de responsabiliza\u00e7\u00e3o entre publicadores, corretores e consumidores. Depois que a mensagem \u00e9 entregue ao corretor, \u00e9 trabalho dele n\u00e3o perder a mensagem. Quando o corretor confirma ao publicador que recebeu a mensagem, n\u00e3o esperamos que ela seja perdida. Mas veremos que isso realmente pode acontecer, dependendo da configura\u00e7\u00e3o do seu corretor e publicador.<\/p>\n<h1>Primitivos de resili\u00eancia de um \u00fanico n\u00f3<\/h1>\n<p><\/p>\n<h3>Filas resistentes \/ roteamento<\/h3>\n<p>\nNo RabbitMQ, existem dois tipos de filas: dur\u00e1veis (durable) e n\u00e3o dur\u00e1veis (non-durable). Todas as filas s\u00e3o armazenadas no banco de dados Mnesia. Filas dur\u00e1veis s\u00e3o reapresentadas ao iniciar o n\u00f3 e, assim, sobrevivem a rein\u00edcios, falhas de sistema ou de servidor (desde que os dados sejam mantidos). Isso significa que enquanto voc\u00ea declarar o roteamento (exchange) e a fila como dur\u00e1veis, a infraestrutura de filas\/roteamento retornar\u00e1 ao modo operacional.<\/p>\n<p>Filas n\u00e3o dur\u00e1veis e roteamento s\u00e3o eliminados ao reiniciar o n\u00f3.<\/p>\n<h3>Mensagens dur\u00e1veis<\/h3>\n<p>\nO fato de uma fila ser dur\u00e1vel n\u00e3o significa que todas as suas mensagens sobreviver\u00e3o ao rein\u00edcio do n\u00f3. Apenas as mensagens marcadas pelo publicador como <i>dur\u00e1veis<\/i> (persistent) ser\u00e3o recuperadas. Mensagens dur\u00e1veis realmente criam uma carga adicional no broker, mas se a perda de uma mensagem for inaceit\u00e1vel, n\u00e3o h\u00e1 outra alternativa.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/8b8e2de4ef82bf8497960657aac0ddb0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 1. Matriz de durabilidade<\/i><\/p>\n<h1>Clusteriza\u00e7\u00e3o com espelhamento de filas<\/h1>\n<p>\nPara sobreviver \u00e0 perda do broker, precisamos de redund\u00e2ncia. Podemos unir v\u00e1rios n\u00f3s RabbitMQ em um cluster e, em seguida, adicionar redund\u00e2ncia adicional atrav\u00e9s da replica\u00e7\u00e3o de filas entre v\u00e1rios n\u00f3s. Assim, se um n\u00f3 falhar, n\u00e3o perderemos dados e permaneceremos acess\u00edveis. <\/p>\n<p>Espelhamento de filas:<\/p>\n<ul>\n<li>uma fila principal (mestre), que recebe todos os comandos de grava\u00e7\u00e3o e leitura\n<\/li>\n<li>uma ou v\u00e1rias r\u00e9plicas, que recebem todas as mensagens e metadados da fila principal. Essas r\u00e9plicas existem n\u00e3o para escalabilidade, mas exclusivamente para redund\u00e2ncia.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/35f3d4bdc4f5e10da0e40eb91c5d8280.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 2. Espelhamento de filas<\/i><\/p>\n<p>O espelhamento \u00e9 configurado atrav\u00e9s de uma pol\u00edtica correspondente. Nela, \u00e9 poss\u00edvel escolher o coeficiente de replica\u00e7\u00e3o e at\u00e9 mesmo os n\u00f3s onde a fila deve ser hospedada. Exemplos:<\/p>\n<ul>\n<li><code>ha-mode: all<\/code>\n<\/li>\n<li><code>ha-mode: exactly, ha-params: 2<\/code> (um mestre e uma r\u00e9plica)\n<\/li>\n<li><code>ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2<\/code><\/li>\n<\/ul>\n<p><\/p>\n<h1>Confirma\u00e7\u00e3o para o publicador<\/h1>\n<p>\nPara garantir a grava\u00e7\u00e3o consistente, s\u00e3o necess\u00e1rias confirma\u00e7\u00f5es do editor (Publisher Confirms). Sem elas, h\u00e1 risco de perda de mensagens. A confirma\u00e7\u00e3o \u00e9 enviada ao editor ap\u00f3s a grava\u00e7\u00e3o da mensagem no disco. O RabbitMQ grava mensagens no disco n\u00e3o ao receb\u00ea-las, mas em uma base peri\u00f3dica, na ordem de algumas centenas de milissegundos. Quando a fila \u00e9 espelhada, a confirma\u00e7\u00e3o \u00e9 enviada apenas depois que todos os espelhos tamb\u00e9m gravaram sua c\u00f3pia da mensagem no disco. Isso significa que o uso de confirma\u00e7\u00f5es adiciona alguma lat\u00eancia, mas se a seguran\u00e7a dos dados \u00e9 importante, elas s\u00e3o necess\u00e1rias.<\/p>\n<h1>Fila \u00e0 prova de falhas<\/h1>\n<p>\nQuando o broker \u00e9 desligado ou falha, todas as filas principais (mestres) neste n\u00f3 falham junto com ele. O cluster ent\u00e3o seleciona o espelho mais antigo de cada mestre e o promove como novo mestre.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/8d8227c00643f35e0dc752b6617e18fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 3. V\u00e1rias filas espelhadas e suas pol\u00edticas<\/i><\/p>\n<p>O Broker 3 falha. Observe que o espelho da Fila C no Broker 2 \u00e9 promovido a mestre. Tamb\u00e9m note que um novo espelho para a Fila C \u00e9 criado no Broker 1. O RabbitMQ sempre tenta manter a taxa de replica\u00e7\u00e3o especificada em suas pol\u00edticas.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/d08b3ada22e79686d448714f7bab009a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 4. Broker 3 falha, causando a falha da fila C<\/i> <\/p>\n<p>O pr\u00f3ximo Broker 1 falha! S\u00f3 temos um broker restante. O espelho da Fila B \u00e9 promovido a mestre.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/dcc1d542c40c441194fd07e51046c619.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 5<\/i><\/p>\n<p>Recuperamos o Broker 1. Independentemente de qu\u00e3o bem os dados sobreviveram \u00e0 perda e \u00e0 recupera\u00e7\u00e3o do broker, todas as mensagens espelhadas da fila s\u00e3o descartadas ao reiniciar. \u00c9 importante notar isso, pois haver\u00e1 consequ\u00eancias. Em breve, abordaremos essas consequ\u00eancias. Assim, o Broker 1 agora \u00e9 novamente um membro do cluster, e o cluster tenta seguir as pol\u00edticas e, portanto, cria espelhos no Broker 1.<\/p>\n<p>Neste caso, a perda do Broker 1 foi completa, assim como a perda dos dados, portanto a Fila B n\u00e3o espelhada foi totalmente perdida.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/7ac7ab65ea6dff9c5a49372c04c83a37.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 6. O Broker 1 volta ao funcionamento<\/i><\/p>\n<p>O Broker 3 voltou ao funcionamento, ent\u00e3o as filas A e B est\u00e3o recuperando os espelhos criados nele para atender \u00e0s suas pol\u00edticas de HA. Mas agora todas as filas principais est\u00e3o em um \u00fanico n\u00f3! Isso n\u00e3o \u00e9 ideal, \u00e9 melhor ter uma distribui\u00e7\u00e3o uniforme entre os n\u00f3s. Infelizmente, n\u00e3o h\u00e1 muitas op\u00e7\u00f5es para reequilibrar os mestres. Voltaremos a este problema mais tarde, pois precisamos primeiro considerar a sincroniza\u00e7\u00e3o da fila. <\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/a54e53bb01e2f830a54f88acaa668984.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 7. O Broker 3 retorna ao funcionamento. Todas as filas principais em um \u00fanico n\u00f3!<\/i><\/p>\n<p>Assim, agora voc\u00ea deve ter uma ideia de como os espelhos garantem redund\u00e2ncia e resist\u00eancia a falhas. Isso garante a disponibilidade em caso de falha de um n\u00f3 e protege contra perda de dados. Mas ainda n\u00e3o terminamos, pois na verdade tudo \u00e9 muito mais complexo.<\/p>\n<h1>Sincroniza\u00e7\u00e3o<\/h1>\n<p>\nAo criar um novo espelho, todas as novas mensagens sempre ser\u00e3o replicadas para esse espelho e quaisquer outros. Quanto aos dados existentes na fila principal, podemos replic\u00e1-los no novo espelho, que se torna uma c\u00f3pia completa do mestre. Tamb\u00e9m podemos optar por n\u00e3o replicar mensagens existentes e permitir que a fila principal e o novo espelho se sincronizem ao longo do tempo, enquanto novas mensagens s\u00e3o adicionadas ao final e mensagens existentes s\u00e3o removidas do in\u00edcio da fila principal.<\/p>\n<p>Essa sincroniza\u00e7\u00e3o \u00e9 realizada automaticamente ou manualmente e \u00e9 gerenciada atrav\u00e9s de uma pol\u00edtica de filas. Vamos considerar um exemplo.<\/p>\n<p>Temos duas filas espelhadas. A fila A \u00e9 sincronizada automaticamente e a fila B manualmente. Ambas as filas t\u00eam dez mensagens.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/304f2a475fdd0cb6d3069140c667a0a7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 8. Duas filas com diferentes modos de sincroniza\u00e7\u00e3o<\/i><\/p>\n<p>Agora estamos perdendo o Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/49114966f440c407488bb467ff6dbf93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 9. O Broker 3 caiu<\/i><\/p>\n<p>O Broker 3 retorna ao funcionamento. O cluster cria um espelho para cada fila em um novo n\u00f3 e sincroniza automaticamente a nova Fila A com o mestre. No entanto, o espelho da nova Fila B permanece vazio. Portanto, temos total redund\u00e2ncia da Fila A e apenas um espelho para as mensagens existentes da Fila B.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/adffc1f5eff8806edbd83772f338d67f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 10. O novo espelho da Fila A recebe todas as mensagens existentes, enquanto o novo espelho da Fila B n\u00e3o recebe nenhuma.<\/i><\/p>\n<p>Em ambas as filas, mais dez mensagens s\u00e3o recebidas. Em seguida, o Broker 2 falha e a Fila A reverte para o espelho mais antigo, que est\u00e1 no Broker 1. N\u00e3o h\u00e1 perda de dados durante a falha. Na Fila B, h\u00e1 vinte mensagens no mestre e apenas dez no espelho, pois essa fila nunca replicou as dez mensagens originais.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/c6cfef4bced5627bf243c2f020a42646.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 11. A Fila A reverte para o Broker 1 sem perda de mensagens.<\/i><\/p>\n<p>Em ambas as filas, mais dez mensagens s\u00e3o recebidas. Agora, o Broker 1 falha. A Fila A muda para o espelho sem perder mensagens. No entanto, a Fila B enfrenta problemas. Nesse est\u00e1gio, podemos otimizar a disponibilidade ou consist\u00eancia. <\/p>\n<p>Se quisermos otimizar a disponibilidade, a pol\u00edtica <b><i>ha-promote-on-failure<\/i><\/b> deve ser definida como <b><i>always<\/i><\/b>. Esse \u00e9 o valor padr\u00e3o, ent\u00e3o podemos simplesmente n\u00e3o especificar a pol\u00edtica. Nesse caso, em ess\u00eancia, estamos permitindo falhas em espelhos n\u00e3o sincronizados. Isso resultar\u00e1 em perda de mensagens, mas a fila permanece acess\u00edvel para leitura e grava\u00e7\u00e3o.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/cd704cf4397184c212e1576b986abbaa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 12. A Fila A reverte para o Broker 3 sem perda de mensagens. A Fila B reverte para o Broker 3 com perda de dez mensagens.<\/i><\/p>\n<p>Tamb\u00e9m podemos definir <code>ha-promote-on-failure<\/code> como valor <code>when-synced<\/code>. Nesse caso, em vez de reverter para o espelho, a fila aguardar\u00e1 at\u00e9 que o Broker 1 com seus dados retorne ao modo operacional. Ap\u00f3s seu retorno, a fila principal volta a estar no Broker 1 sem perda de dados. A disponibilidade \u00e9 sacrificada em nome da seguran\u00e7a dos dados. Mas esse \u00e9 um modo arriscado que pode levar at\u00e9 mesmo \u00e0 perda total de dados, o que abordaremos em breve.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/03fed936fe75220e22f68432ca81b654.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 13. A Fila B permanece indispon\u00edvel ap\u00f3s a falha do Broker 1.<\/i><\/p>\n<p>Voc\u00ea pode se perguntar: \u201cTalvez seja melhor nunca usar sincroniza\u00e7\u00e3o autom\u00e1tica?\u201d. A resposta \u00e9 que a sincroniza\u00e7\u00e3o \u00e9 uma opera\u00e7\u00e3o bloqueadora. Durante a sincroniza\u00e7\u00e3o, a fila principal n\u00e3o pode executar nenhuma opera\u00e7\u00e3o de leitura ou grava\u00e7\u00e3o!<\/p>\n<p>Vamos considerar um exemplo. Agora temos filas muito grandes. Como elas podem crescer tanto? Por v\u00e1rias raz\u00f5es:<\/p>\n<ul>\n<li>As filas n\u00e3o est\u00e3o sendo ativamente usadas.\n<\/li>\n<li>Estas s\u00e3o filas de alta velocidade, e neste momento os consumidores est\u00e3o funcionando lentamente. \n<\/li>\n<li>Estas s\u00e3o filas de alta velocidade, houve uma falha, e os consumidores est\u00e3o se recuperando.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/dd4b0fd70cbbc0b7defc06536157770d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 14. Duas grandes filas com diferentes modos de sincroniza\u00e7\u00e3o<\/i><\/p>\n<p>Agora cai o Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/8c31cfdf485ab4c9dfe13e86a151df4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 15. O Broker 3 cai, deixando um mestre e um espelho em cada fila<\/i><\/p>\n<p>O Broker 3 retorna ao funcionamento, e novos espelhos s\u00e3o criados. A Fila Principal A come\u00e7a a replicar mensagens existentes em um novo espelho, e durante esse tempo a Fila fica indispon\u00edvel. A replica\u00e7\u00e3o de dados leva duas horas, resultando em duas horas de inatividade para essa Fila!<\/p>\n<p>No entanto, a Fila B permanece dispon\u00edvel durante todo o per\u00edodo. Ela sacrificou alguma redund\u00e2ncia em prol da disponibilidade.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/28e641300a1c3f4d70e29a16db51521e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 16. A fila permanece indispon\u00edvel durante a sincroniza\u00e7\u00e3o<\/i><\/p>\n<p>Ap\u00f3s duas horas, a Fila A tamb\u00e9m se torna dispon\u00edvel e pode novamente come\u00e7ar a aceitar opera\u00e7\u00f5es de leitura e grava\u00e7\u00e3o.<\/p>\n<h3>Atualiza\u00e7\u00f5es<\/h3>\n<p>\nEsse comportamento de bloqueio durante a sincroniza\u00e7\u00e3o dificulta a atualiza\u00e7\u00e3o de clusters com filas muito grandes. Em algum momento, o n\u00f3 com o mestre precisa ser reiniciado, o que significa mudar para o espelho ou desligar a fila durante a atualiza\u00e7\u00e3o do servidor. Se optarmos pela mudan\u00e7a, perderemos mensagens se os espelhos n\u00e3o estiverem sincronizados. Por padr\u00e3o, durante a desconex\u00e3o do broker, a mudan\u00e7a para o espelho n\u00e3o sincronizado n\u00e3o \u00e9 realizada. Isso significa que, assim que o broker retorna, n\u00e3o perdemos nenhuma mensagem, com o \u00fanico dano sendo a inatividade da fila. As regras de comportamento durante a desconex\u00e3o do broker s\u00e3o definidas pela pol\u00edtica <code>ha-promote-on-shutdown<\/code>. \u00c9 poss\u00edvel definir um dos dois valores:<\/p>\n<ul>\n<li><code>always<\/code>= habilitar a mudan\u00e7a para espelhos n\u00e3o sincronizados\n<\/li>\n<li><code>when-synced<\/code>= mudan\u00e7a apenas para espelho sincronizado, caso contr\u00e1rio, a fila se torna indispon\u00edvel para leitura e grava\u00e7\u00e3o. A fila retorna ao funcionamento assim que o broker voltar<\/li>\n<\/ul>\n<p>\nDe qualquer forma, com filas grandes, \u00e9 preciso escolher entre a perda de dados e a indisponibilidade.<\/p>\n<h3>Quando a disponibilidade aumenta a seguran\u00e7a dos dados<\/h3>\n<p>\nAntes de tomar uma decis\u00e3o, \u00e9 preciso considerar mais uma complica\u00e7\u00e3o. Embora a sincroniza\u00e7\u00e3o autom\u00e1tica seja melhor para redund\u00e2ncia, como isso afeta a seguran\u00e7a dos dados? Certamente, gra\u00e7as \u00e0 melhor redund\u00e2ncia, o RabbitMQ tem menor probabilidade de perder mensagens existentes, mas e quanto \u00e0s novas mensagens dos publishers?<\/p>\n<p>Aqui \u00e9 preciso considerar o seguinte:<\/p>\n<ul>\n<li>Um publisher pode simplesmente retornar um erro e o servi\u00e7o superior ou o usu\u00e1rio tentarem novamente mais tarde?\n<\/li>\n<li>Um publisher pode salvar a mensagem localmente ou em um banco de dados, para tentar novamente mais tarde?<\/li>\n<\/ul>\n<p>\nSe um publisher s\u00f3 pode descartar a mensagem, ent\u00e3o, na verdade, a melhoria da disponibilidade tamb\u00e9m aumenta a seguran\u00e7a dos dados.<\/p>\n<p>Portanto, \u00e9 preciso buscar um equil\u00edbrio, e a solu\u00e7\u00e3o depende da situa\u00e7\u00e3o espec\u00edfica.<\/p>\n<h1>Problemas com ha-promote-on-failure=when-synced<\/h1>\n<p>\nIdeia <i><b>ha-promote-on-failure<\/b><\/i>= <i><b>when-synced<\/b><\/i> \u00e9 que evitamos a mudan\u00e7a para um espelho n\u00e3o sincronizado e, assim, evitamos a perda de dados. A fila permanece indispon\u00edvel para leitura ou grava\u00e7\u00e3o. Em vez disso, tentamos recuperar o broker que falhou com dados intactos, para que ele possa retomar como mestre sem perda de dados. <\/p>\n<p>Mas (e isso \u00e9 um grande mas) se o broker perdeu seus dados, temos um grande problema: a fila foi perdida! Todos os dados se foram! Mesmo que voc\u00ea tenha espelhos que em grande parte acompanham a fila principal, esses espelhos tamb\u00e9m s\u00e3o descartados.<\/p>\n<p>Para re-adicionar um n\u00f3 com o mesmo nome, dizemos ao cluster para esquecer o n\u00f3 perdido (com o comando <i>rabbitmqctl forget_cluster_node<\/i>) e iniciar um novo broker com o mesmo nome de host. Enquanto o cluster lembrar do n\u00f3 perdido, ele lembrar\u00e1 da fila antiga e dos espelhos n\u00e3o sincronizados. Quando dizemos ao cluster para esquecer o n\u00f3 perdido, essa fila tamb\u00e9m \u00e9 esquecida. Agora precisamos declar\u00e1-la novamente. Perdemos todos os dados, embora tiv\u00e9ssemos espelhos com um conjunto de dados parcial. Teria sido melhor mudar para um espelho n\u00e3o sincronizado!<\/p>\n<p>Portanto, a sincroniza\u00e7\u00e3o manual (e a n\u00e3o realiza\u00e7\u00e3o de sincroniza\u00e7\u00e3o) em conjunto com <code>ha-promote-on-failure=when-synced<\/code>, na minha opini\u00e3o, \u00e9 bastante arriscada. Documentos afirmam que essa op\u00e7\u00e3o existe para seguran\u00e7a dos dados, mas \u00e9 uma faca de dois gumes.<\/p>\n<h1>Reequil\u00edbrio de mestres<\/h1>\n<p>\nComo prometido, voltamos ao problema de acumula\u00e7\u00e3o de todos os mestres em um ou v\u00e1rios n\u00f3s. Isso pode ocorrer at\u00e9 mesmo em um processo de atualiza\u00e7\u00e3o \u2018rolling\u2019 do cluster. Em um cluster com tr\u00eas n\u00f3s, todas as filas principais podem se acumular em um ou dois n\u00f3s.<\/p>\n<p>O reequil\u00edbrio de mestres pode ser problem\u00e1tico por duas raz\u00f5es:<\/p>\n<ul>\n<li>N\u00e3o h\u00e1 boas ferramentas para realizar a reequilibra\u00e7\u00e3o<\/li>\n<li>Sincroniza\u00e7\u00e3o de filas<\/li>\n<\/ul>\n<p>\nPara o rebalanceamento, h\u00e1 um componente de terceiros <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Ayanda-D\/rabbitmq-queue-master-balancer\">para integra\u00e7\u00e3o com o Jenkins, desenvolvido pela equipe da T-Systems Multimedia Solutions. Em cada evento de in\u00edcio de verifica\u00e7\u00e3o, cont\u00e9m informa\u00e7\u00f5es sobre o servi\u00e7o, n\u00famero da compila\u00e7\u00e3o e hor\u00e1rio do teste. O plug-in coleta valores de desempenho durante a compila\u00e7\u00e3o, avalia-os e compara o resultado com compila\u00e7\u00f5es anteriores e requisitos n\u00e3o funcionais.<\/a><\/noindex>, que n\u00e3o \u00e9 oficialmente suportado. Em rela\u00e7\u00e3o aos plugins de terceiros, o guia do RabbitMQ <noindex><a rel=\"nofollow\" href=\"https:\/\/www.rabbitmq.com\/upgrade.html\">est\u00e1 escrito<\/a><\/noindex>: \"O plugin fornece algumas ferramentas adicionais de configura\u00e7\u00e3o e relat\u00f3rios, mas n\u00e3o \u00e9 suportado e n\u00e3o foi verificado pela equipe do RabbitMQ. Use por sua pr\u00f3pria conta e risco\".<\/p>\n<p>H\u00e1 tamb\u00e9m um truque para mover a fila principal por meio de pol\u00edticas de HA. O guia menciona <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/rabbitmq\/support-tools\/blob\/master\/scripts\/rebalance-queue-masters\">script<\/a><\/noindex> para isso. Ele funciona da seguinte forma:<\/p>\n<ul>\n<li>Remove todos os espelhos usando uma pol\u00edtica tempor\u00e1ria com uma prioridade mais alta do que a pol\u00edtica de HA existente.\n<\/li>\n<li>Altera a pol\u00edtica de HA tempor\u00e1ria para usar o modo 'n\u00f3s', especificando o n\u00f3 para o qual a fila principal deve ser movida.\n<\/li>\n<li>Sincroniza a fila para for\u00e7ar a migra\u00e7\u00e3o.\n<\/li>\n<li>Ap\u00f3s a conclus\u00e3o da migra\u00e7\u00e3o, remove a pol\u00edtica tempor\u00e1ria. A pol\u00edtica original de HA entra em vigor e a quantidade necess\u00e1ria de espelhos \u00e9 criada.<\/li>\n<\/ul>\n<p>\nA desvantagem \u00e9 que essa abordagem pode n\u00e3o funcionar se voc\u00ea tiver filas grandes ou requisitos rigorosos de redund\u00e2ncia.<\/p>\n<p>Agora, vamos ver como os clusters RabbitMQ lidam com divis\u00f5es de rede.<\/p>\n<h1>Divis\u00e3o de Coes\u00e3o<\/h1>\n<p>\nOs n\u00f3s de um sistema distribu\u00eddo s\u00e3o conectados por meio de links de rede, e os links podem e ir\u00e3o falhar. A frequ\u00eancia das falhas depende da infraestrutura local ou da confiabilidade da nuvem escolhida. Em qualquer caso, sistemas distribu\u00eddos devem ser capazes de lidar com isso. Mais uma vez, temos uma escolha entre disponibilidade e consist\u00eancia, e a boa not\u00edcia \u00e9 que o RabbitMQ oferece ambas as op\u00e7\u00f5es (apenas n\u00e3o ao mesmo tempo).<\/p>\n<p>Com o RabbitMQ, temos duas op\u00e7\u00f5es principais:<\/p>\n<ul>\n<li>Permitir a divis\u00e3o l\u00f3gica (split-brain). Isso garante disponibilidade, mas pode causar perda de dados.\n<\/li>\n<li>Proibir a divis\u00e3o l\u00f3gica. Isso pode levar a uma perda tempor\u00e1ria de disponibilidade, dependendo de como os clientes se conectam ao cluster. Tamb\u00e9m pode resultar em completa indisponibilidade no cluster de dois n\u00f3s.<\/li>\n<\/ul>\n<p>\nMas o que \u00e9 divis\u00e3o l\u00f3gica? \u00c9 quando o cluster \u00e9 dividido em dois devido \u00e0 perda de conex\u00f5es de rede. De cada lado, os espelhos se elevam a mestres, de forma que no final h\u00e1 v\u00e1rios mestres para cada fila.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/d880a935df450fb994edfed0715e026e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 17. Fila principal e dois espelhos, cada um em um n\u00f3 separado. Em seguida, ocorre uma falha de rede, e um espelho se separa. O n\u00f3 separado v\u00ea que os outros dois falharam e promove seus espelhos a mestre. Agora temos duas filas principais, ambas permitindo grava\u00e7\u00e3o e leitura.<\/i> <\/p>\n<p>Se os publishers enviam dados para ambos os mestres, teremos duas c\u00f3pias divergentes da fila.<\/p>\n<p>Modos diferentes do RabbitMQ garantem disponibilidade ou consist\u00eancia.<\/p>\n<h3>Modo Ignore (padr\u00e3o)<\/h3>\n<p>\nEsse modo garante disponibilidade. Ap\u00f3s a perda de conectividade, ocorre uma divis\u00e3o l\u00f3gica. Ap\u00f3s a restaura\u00e7\u00e3o da conectividade, o administrador deve decidir a qual divis\u00e3o dar prefer\u00eancia. O lado perdedor ser\u00e1 reiniciado, e todos os dados acumulados desse lado ser\u00e3o perdidos.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/4d82c13b5ef21837ba819f5c246a1e41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 18. Tr\u00eas publishers est\u00e3o conectados a tr\u00eas brokers. Internamente, o cluster direciona todas as solicita\u00e7\u00f5es para a fila principal no Broker 2.<\/i><\/p>\n<p>Agora perdemos o Broker 3. Ele v\u00ea que os outros brokers falharam e promove seu espelho a mestre. Isso resulta em uma divis\u00e3o l\u00f3gica.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/c7e01d51b24023bacdd93cfad95c9eab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 19. Divis\u00e3o l\u00f3gica (split-brain). As grava\u00e7\u00f5es v\u00e3o para duas filas principais, e duas c\u00f3pias se separam.<\/i><\/p>\n<p>A conectividade \u00e9 restaurada, mas a divis\u00e3o l\u00f3gica permanece. O administrador deve escolher manualmente o lado perdedor. No exemplo abaixo, o administrador reinicia o Broker 3. Todas as mensagens que ele n\u00e3o conseguiu transmitir s\u00e3o perdidas.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/51c3ee15024d3c83ba625e3ff9cdeb90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 20. O administrador desativa o Broker 3.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/0bac8e33de25c0c5381d336d26464858.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 21. O administrador inicia o Broker 3, e ele se junta ao cluster, perdendo todas as mensagens que estavam l\u00e1.<\/i><\/p>\n<p>Durante a perda de conectividade e ap\u00f3s sua restaura\u00e7\u00e3o, o cluster e essa fila estavam dispon\u00edveis para leitura e grava\u00e7\u00e3o.<\/p>\n<h3>Modo Autoheal<\/h3>\n<p>\nFunciona de maneira semelhante ao modo Ignore, exceto que o pr\u00f3prio cluster escolhe automaticamente o lado perdedor ap\u00f3s a separa\u00e7\u00e3o e a restaura\u00e7\u00e3o da conectividade. O lado perdedor retorna ao cluster vazio, e a fila perde todas as mensagens que foram enviadas apenas para aquele lado.<\/p>\n<h3>Modo Pause Minority<\/h3>\n<p>\nSe n\u00e3o quisermos permitir a separa\u00e7\u00e3o l\u00f3gica, nossa \u00fanica op\u00e7\u00e3o \u00e9 desistir de ler e gravar no lado menor ap\u00f3s a divis\u00e3o do cluster. Quando o broker detecta que est\u00e1 no lado menor, ele suspende suas opera\u00e7\u00f5es, ou seja, fecha todas as conex\u00f5es existentes e rejeita novas. Ele verifica a recupera\u00e7\u00e3o da conectividade uma vez por segundo. Assim que a conectividade for restaurada, ele retoma suas opera\u00e7\u00f5es e se reintegra ao cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/7a51cf509b2c94e2ae100c7dedd9d21a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 22. Tr\u00eas publishers est\u00e3o conectados a tr\u00eas brokers. Internamente, o cluster direciona todas as solicita\u00e7\u00f5es para a fila principal no Broker 2.<\/i><\/p>\n<p>Em seguida, os Brokers 1 e 2 se separam do Broker 3. Em vez de promover seu espelho a mestre, o Broker 3 suspende suas opera\u00e7\u00f5es e fica indispon\u00edvel.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/c12ec38a47e1f8ccceebfa1854f54f21.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 23. O Broker 3 suspende suas opera\u00e7\u00f5es, desconecta todos os clientes e rejeita solicita\u00e7\u00f5es de conex\u00e3o.<\/i><\/p>\n<p>Assim que a conectividade for restaurada, ele volta ao cluster.<\/p>\n<p>Vamos considerar outro exemplo onde a fila principal est\u00e1 no Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/4cc6a28270f00a280ecb5af5252f4e07.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 24. A fila principal no Broker 3.<\/i><\/p>\n<p>Em seguida, ocorre a mesma perda de conectividade. O Broker 3 entra em pausa, pois est\u00e1 no lado menor. Do outro lado, os n\u00f3s veem que o Broker 3 caiu, ent\u00e3o um espelho mais antigo do Broker 1 e 2 \u00e9 promovido a mestre.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/d0d032385533bb53c5a95927afcd3119.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 25. Transi\u00e7\u00e3o para o Broker 2 na aus\u00eancia do Broker 3.<\/i><\/p>\n<p>Quando a conectividade for restaurada, o Broker 3 se juntar\u00e1 ao cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: Fault Tolerance and High Availability in Clusters\" src=\"\/wp-content\/uploads\/2019\/11\/53f8186a040ae07724ef59cf79b72a0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 26. O cluster voltou a operar normalmente.<\/i><\/p>\n<p>Aqui \u00e9 importante entender que obtivemos consist\u00eancia, mas tamb\u00e9m podemos obter disponibilidade. <i><b>se<\/b><\/i> vamos traduzir os clientes com sucesso para a maior parte da se\u00e7\u00e3o. Para a maioria das situa\u00e7\u00f5es, eu pessoalmente escolheria o modo Pause Minority, mas isso realmente depende do caso espec\u00edfico.<\/p>\n<p>Para garantir a disponibilidade, \u00e9 importante assegurar que os clientes se conectem com sucesso ao n\u00f3. Vamos considerar nossas op\u00e7\u00f5es.<\/p>\n<h1>Garantindo a conectividade dos clientes<\/h1>\n<p>\nTemos v\u00e1rias op\u00e7\u00f5es para redirecionar clientes para a parte principal do cluster ou para n\u00f3s operacionais ap\u00f3s a perda de conectividade (depois que um n\u00f3 falha). Primeiro, vamos lembrar que uma fila espec\u00edfica \u00e9 alocada a um determinado n\u00f3, mas o roteamento e as pol\u00edticas s\u00e3o replicados em todos os n\u00f3s. Os clientes podem se conectar a qualquer n\u00f3, e o roteamento interno os direcionar\u00e1 para onde precisam ir. No entanto, quando um n\u00f3 \u00e9 interrompido, ele rejeita conex\u00f5es, portanto, os clientes devem se conectar a outro n\u00f3. Se um n\u00f3 falha, ele n\u00e3o pode fazer nada.<\/p>\n<p>Nossas op\u00e7\u00f5es:<\/p>\n<ul>\n<li>O acesso ao cluster \u00e9 feito por meio de um balanceador de carga, que simplesmente percorre os n\u00f3s em ciclos, enquanto os clientes tentam se reconectar at\u00e9 que a conex\u00e3o seja bem-sucedida. Se um n\u00f3 n\u00e3o estiver funcionando ou estiver parado, as tentativas de conex\u00e3o para esse n\u00f3 falhar\u00e3o, mas as tentativas subsequentes ser\u00e3o direcionadas a outros servidores (em modo c\u00edclico). Isso \u00e9 adequado para uma perda tempor\u00e1ria de conectividade ou um servidor que falhou e ser\u00e1 rapidamente reiniciado.\n<\/li>\n<li>Acesso ao cluster atrav\u00e9s de um balanceador de carga e remo\u00e7\u00e3o de n\u00f3s parados\/falhados da lista assim que forem detectados. Se isso for feito rapidamente, e se os clientes puderem tentar reconectar, teremos disponibilidade cont\u00ednua.\n<\/li>\n<li>Fornecer a cada cliente uma lista de todos os n\u00f3s, e o cliente, ao se conectar, escolhe aleatoriamente um deles. Se ao tentar se conectar ele receber um erro, ele passa para o pr\u00f3ximo n\u00f3 da lista at\u00e9 conseguir se conectar.\n<\/li>\n<li>Remover o tr\u00e1fego do n\u00f3 falhado\/parado usando DNS. Isso \u00e9 feito com um pequeno TTL.<\/li>\n<\/ul>\n<p><\/p>\n<h1>Como resultado, obtemos um servi\u00e7o de \"monitoramento como servi\u00e7o\", automatizado na linha de produ\u00e7\u00e3o de integra\u00e7\u00e3o cont\u00ednua. O desenvolvedor ou testador precisa apenas definir a lista de m\u00e9tricas em um arquivo JSON, e tudo o mais acontece automaticamente. Obtemos um controle de qualidade transparente dos lan\u00e7amentos: todas as notifica\u00e7\u00f5es sobre desempenho, consumo de recursos ou regress\u00f5es arquitet\u00f4nicas.<\/h1>\n<p>\nA clusteriza\u00e7\u00e3o do RabbitMQ tem suas vantagens e desvantagens. As desvantagens mais s\u00e9rias incluem:<\/p>\n<ul>\n<li>ao se unir ao cluster, os n\u00f3s descartam seus dados;\n<\/li>\n<li>a sincroniza\u00e7\u00e3o bloqueante resulta na indisponibilidade da fila.<\/li>\n<\/ul>\n<p>\nTodas as decis\u00f5es dif\u00edceis decorrem dessas duas caracter\u00edsticas da arquitetura. Se o RabbitMQ pudesse salvar dados ao reconectar o cluster, a sincroniza\u00e7\u00e3o ocorreria mais rapidamente. Se ele tivesse capacidade de sincroniza\u00e7\u00e3o sem bloqueio, suportaria filas maiores com mais efici\u00eancia. Resolver esses dois problemas melhoraria significativamente as caracter\u00edsticas do RabbitMQ como uma tecnologia de troca de mensagens resiliente e de alta disponibilidade. Eu n\u00e3o recomendaria o RabbitMQ com clusteriza\u00e7\u00e3o nas seguintes situa\u00e7\u00f5es:<\/p>\n<ul>\n<li>Rede n\u00e3o confi\u00e1vel.\n<\/li>\n<li>Armazenamento n\u00e3o confi\u00e1vel.\n<\/li>\n<li>Filas muito grandes.<\/li>\n<\/ul>\n<p>\nQuanto \u00e0s configura\u00e7\u00f5es para alta disponibilidade, considere as seguintes:<\/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> (ou <code>autoheal<\/code>)\n<\/li>\n<li>mensagens persistentes\n<\/li>\n<li>garanta que os clientes se conectem ao n\u00f3 ativo quando um n\u00f3 falha<\/li>\n<\/ul>\n<p>\nPara consist\u00eancia (seguran\u00e7a de dados), considere as seguintes configura\u00e7\u00f5es:<\/p>\n<ul>\n<li>Publisher Confirms e Acknowledgements Manuais do lado do consumidor\n<\/li>\n<li><code>ha-promote-on-failure=when-synced<\/code>, se os publicadores puderem tentar novamente mais tarde e se voc\u00ea tiver um armazenamento muito confi\u00e1vel! Caso contr\u00e1rio, defina <code>=always<\/code>.\n<\/li>\n<li><code>ha-sync-mode=automatic<\/code> (mas para filas grandes inativas, pode ser necess\u00e1rio o modo manual; al\u00e9m disso, considere se a indisponibilidade levar\u00e1 \u00e0 perda de mensagens)\n<\/li>\n<li>modo Pause Minority\n<\/li>\n<li>mensagens persistentes<\/li>\n<\/ul>\n<p>\nAinda n\u00e3o abordamos todas as quest\u00f5es de resili\u00eancia e alta disponibilidade; por exemplo, como realizar procedimentos administrativos de forma segura (como atualiza\u00e7\u00f5es cont\u00ednuas). Tamb\u00e9m precisamos falar sobre federa\u00e7\u00e3o e o plugin Shovel.<\/p>\n<p>Se eu perdi mais alguma coisa, por favor, avise.<\/p>\n<p>Veja tamb\u00e9m meu <noindex><a rel=\"nofollow\" href=\"https:\/\/jack-vanlightly.com\/blog\/2018\/9\/10\/how-to-lose-messages-on-a-rabbitmq-cluster\">post<\/a><\/noindex>, onde realizo uma destrui\u00e7\u00e3o no cluster RabbitMQ com Docker e Blockade para testar alguns cen\u00e1rios de perda de mensagens descritos neste artigo.<\/p>\n<p>Artigos anteriores da s\u00e9rie: <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.3 - 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\/pt\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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 contra Kafka: resili\u00eancia e alta disponibilidade em clusters | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/52525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=52525"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/52525\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=52525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=52525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=52525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}