Em sistemas distribuídos e microsserviços , os message brokers são essenciais. Eles permitem comunicação assíncrona , desacopla serviços e aprimoram a confiabilidade e a escalabilidade. A arquitetura moderna depende muito dos message brokers, tornando-os um componente-chave em muitos padrões de design.
Kafka e RabbitMQ são dois dos corretores de mensagens mais populares. Eles são conhecidos por serem confiáveis, eficientes e adaptáveis, com excelente documentação, suporte e comunidades.
RabbitMQ é uma solução gratuita e de código aberto, com licença dupla sob a Apache License 2.0 e Mozilla Public License 2. Ela permite que você a use e modifique conforme necessário. Ela funciona como um corretor de mensagens puro, suportando múltiplos protocolos e oferecendo recursos adicionais.
Kafka, também de código aberto sob a licença Apache 2.0, é mais do que apenas um corretor de mensagens; é uma plataforma de streaming de eventos distribuída. Ele fornece recursos avançados, incluindo Kafka Streams.
Ao comparar RabbitMQ e Kafka, não há solução "melhor"; trata-se de encontrar a melhor opção para sua arquitetura e seus objetivos.
Este artigo o guiará pelos principais recursos e características, comparando os dois diretamente. Ele tem como objetivo fornecer uma compreensão abrangente das diferenças entre Kafka e RabbitMQ, auxiliando você a fazer uma escolha informada com base em seu problema e requisitos específicos.
O RabbitMQ suporta vários protocolos, como:
Por outro lado, o Kafka usa seu protocolo binário baseado em TCP otimizado para alto rendimento e depende de uma abstração de "conjunto de mensagens". Essa abstração permite que solicitações de rede agrupem mensagens, reduzindo a sobrecarga de idas e vindas de rede ao enviar lotes em vez de mensagens individuais. O protocolo personalizado do Kafka permite flexibilidade no desenvolvimento e otimização para cenários de alta carga.
No entanto, o protocolo personalizado também tem desvantagens. Ele isola o Kafka de outros corretores de mensagens, levando a uma falta de interoperabilidade. Ao contrário do RabbitMQ, que é compatível com qualquer cliente AMQP, o Kafka requer o uso de clientes Kafka. No entanto, devido à popularidade do Kafka e aos esforços da comunidade, os clientes Kafka estão disponíveis para muitas linguagens de programação.
A abordagem de roteamento no RabbitMQ e no Kafka difere significativamente.
Os principais componentes do roteamento RabbitMQ:
Antes de nos aprofundarmos nas Trocas, devemos esclarecer mais dois conceitos:
Existem quatro tipos de troca:
*(asterisco) corresponde exatamente a uma palavra.
#(hash) corresponde a zero ou mais palavras.
Por exemplo, uma fila vinculada com a chave de roteamento "apple.*.banana" receberia mensagens com chaves como "apple.orange.banana" ou "apple.strawberry.banana" . Uma fila vinculada com #.banana receberia mensagens com chaves como "apple.banana" ou "apple.orange.banana".
O roteamento do Kafka é mais simples. Os principais componentes são:
Comparado ao RabbitMQ, os recursos de roteamento do Kafka são limitados. Ele não foi projetado para roteamento granular, mas para alto desempenho e escalabilidade.
Uma coisa importante a ser observada aqui:
No RabbitMQ, quando um Consumer recebe uma mensagem de uma Queue, ele a "rouba". Se reconhecido com sucesso, outros Consumers não receberão a mensagem. Os Consumers do Kafka se comportam da mesma forma se estiverem no mesmo Consumer Group. Consumer Group é uma abstração do Kafka, que permite que vários Consumers leiam do mesmo Topic de forma independente, garantindo que cada Consumer Group processe todas as mensagens do Topic.
No RabbitMQ, durabilidade e persistência são características distintas:
Durabilidade. É uma propriedade de Queues e Exchanges. Existem dois tipos de Queues: durable e transient. Uma Queue durável (ou Exchange) armazena seus metadados no disco e pode sobreviver a uma reinicialização do broker. As Transient Queues não.
Persistência. Uma Fila durável não garante a durabilidade da mensagem. Para torná-la durável, você deve configurar a persistência. Quando o Publisher envia uma mensagem, ele pode especificar a propriedade de persistência. Nesse caso, uma mensagem será armazenada no armazenamento de disco interno e estará disponível após a reinicialização do broker.
O Kafka armazena tudo em um disco. Diferentemente do RabbitMQ, que exclui mensagens após o reconhecimento do Consumer, o Kafka retém todas as mensagens até que elas atinjam um limite de tempo de vida (TTL) ou tamanho de disco. Ele permite que as mensagens sejam reprocessadas por um Consumer Group diferente ou pelo mesmo.
Tanto o RabbitMQ quanto o Kafka oferecem suporte a clustering, onde vários corretores trabalham juntos.
No RabbitMQ, o clustering melhora a disponibilidade e garante a segurança dos dados. Se falamos de desempenho, o escalonamento vertical é uma maneira preferível de impulsionar seu RabbitMQ. O escalonamento horizontal pode adicionar sobrecarga de sincronização significativa. Normalmente, você prefere ter um cluster de 3 corretores para garantir a disponibilidade caso um corretor falhe.
O RabbitMQ não oferece suporte para particionamento de filas imediatamente, mas vale a pena mencionar que ele tem
O Kafka escala eficientemente. Ele não só fornece disponibilidade e segurança de dados, mas também melhora o rendimento do processamento de dados. O conceito-chave aqui é particionamento. Cada tópico tem um número configurável de partições. Cada partição opera isoladamente das outras, atuando como um armazenamento e processamento de dados físicos. Você pode replicar cada partição no cluster, o que garante tolerância a falhas. Produtores e consumidores trabalham apenas com a partição principal (ou primária). Se o broker com essa partição cair, o sistema elege uma nova partição primária das réplicas.
Escolher o número certo de partições é crucial. Um grande número de partições retarda a recuperação do sistema em caso de falha do nó. Por outro lado, limita o rendimento e o nível de paralelismo para o grupo de consumidores. Dentro de um grupo de consumidores, cada partição pode trabalhar com apenas um consumidor (que é efetivamente um thread em seu aplicativo). Portanto, ter três partições não faria sentido para ter mais de três consumidores porque o resto ficará ocioso.
O RabbitMQ garante a ordenação dentro de uma única fila. Um consumidor processará mensagens em ordem. No entanto, a situação muda com vários consumidores. Se um consumidor falhar, o sistema retorna as mensagens não confirmadas para a fila, mas o próximo consumidor pode já estar processando o próximo lote. Então, quais são as opções?
RabbitMQ e Kafka oferecem garantias de entrega "pelo menos uma vez", o que significa que duplicatas são possíveis, mas as mensagens serão totalmente processadas pelo menos uma vez.
O Kafka tem mais recursos de entrega:
Como foi mencionado anteriormente, ao abrir mão da flexibilidade de roteamento, o Kafka traz recursos poderosos em troca.
O Kafka oferece bibliotecas poderosas de processamento de streaming:
Com o Kafka Streams, você pode realizar agregações de tempo em seu tópico e enviar os resultados para outro tópico ou banco de dados.
Vamos imaginar que você tenha um tópico com taxas de câmbio entre diferentes pares de moedas e queira agregar dados de um gráfico de abertura-máxima-mínima-fechamento (também OHLC) dentro de períodos de tempo (5 minutos, 30 minutos, 1 hora, etc.).
Uma opção é armazenar dados em um banco de dados de séries temporais, que é adequado para tal processamento. No entanto, você não precisa disso se tiver o Kafka. Usando agregações simples do Kafka Stream, você pode calcular dados OHLC em cima de um tópico do Kafka e colocar os resultados em qualquer banco de dados para consultas posteriores.
O Kafka também permite que você represente mensagens processadas como uma tabela. Ele coloca os resultados da agregação em uma abstração de tabela, que você pode acessar via KSQL. Esse estado de tabela é durável. Se um broker reiniciar, ele restabelecerá o estado mais recente do tópico correspondente.
Como podemos ver, o Kafka vai além da funcionalidade básica de um agente de mensagens e entra no território do processamento em tempo real e ETLs.
Tanto o Kafka quanto o RabbitMQ são excelentes ferramentas para cenários de alta taxa de transferência e baixa latência. A escolha depende das especificidades do caso de uso, arquitetura e requisitos futuros. Por exemplo, o Kafka é ideal para armazenamento de eventos de transação de longo prazo, enquanto o RabbitMQ se destaca em cenários que exigem compatibilidade de protocolo e flexibilidade de roteamento. Quando tanto o RabbitMQ quanto o Kafka estiverem adequados, considere suas necessidades futuras.