Kafka vs NATS: Uma Comparação para Processamento de Mensagens

Em uma arquitetura distribuída, as comunicações entre sistemas formam a base de toda a infraestrutura. O desempenho, a escalabilidade e a confiabilidade da infraestrutura dependem muito de como eventos/mensagens/dados são trocados e persistidos.

Kafka e NATS são duas ferramentas populares para manipulação de streaming e mensagens. Elas têm arquiteturas diferentes e características de desempenho distintas. Elas são adequadas para casos de uso específicos. Neste artigo, compararemos as características do NATS com o Kafka e explicaremos os casos de uso que abordei no trabalho.

1. Arquitetura e Complexidade

NATS

A infraestrutura do NATS tem dois componentes principais:

NATS Core

O NATS Core é a estrutura base de mensagens. Isso suporta Publish-Subscribe (permite que mensagens sejam transmitidas para vários assinantes), Request-Reply (habilita comunicação síncrona) e Grupos de Fila (facilita o balanceamento de carga entre vários assinantes dentro de um grupo).

Isso é projetado para simplicidade, baixa latência, alto desempenho e escalabilidade. Ele se destaca em cenários que exigem baixa latência e alta taxa de transferência. No entanto, o NATS Core sozinho oferece apenas entrega não garantida, o que significa que as mensagens são entregues apenas a assinantes ativos. Os dados serão perdidos se os assinantes estiverem offline. O NATS Core é uma boa opção quando velocidade e escala têm prioridade sobre durabilidade.

JetStream

JetStream traz capacidades de persistência ao topo do Core NATS. Isso ajudou a fornecer durabilidade e confiabilidade às mensagens. Permite que mensagens ou eventos sejam persistidos (disco ou memória) e reproduzidos. Mensagens persistidas podem ser reproduzidas para assinantes novos ou em recuperação. Com JetStream, os usuários obtêm recursos adicionais:

  1. Retenção de stream: Por quanto tempo as mensagens são retidas. Pode ser baseado em tamanho, tempo ou limites do consumidor.
  2. Durabilidade do consumidor: Permitindo que os consumidores retomem de onde pararam.
  3. Reconhecimento de mensagem: Isso garante a confiabilidade da entrega.

JetStream adiciona uma camada de complexidade ao Core NATS. No entanto, isso traz o importante recurso de suportar os casos de uso de entrega garantida, persistência e capacidade de reprodução.

Kafka

O Kafka é um sistema de mensagens distribuído construído com base em uma arquitetura de corretor baseada em log. Os dados no Kafka são organizados em Tópicos e podem ter várias partições. Os consumidores estão conectados a essas partições. Essa arquitetura permite que o Kafka paralelize o consumo de mensagens para um único tópico. Os dados são anexados a um tópico/partições sequencialmente. O Kafka garante a ordem em uma partição. Em um cluster Kafka, pode haver muitos corretores, cada um gerenciando uma lista de tópicos e partições. Para alcançar alta disponibilidade e evitar a perda de dados, o Kafka depende de um fator de replicação, onde as partições são replicadas em vários corretores do Kafka. Como você pode ver, existem vários componentes que devem ser gerenciados para alcançar alta taxa de transferência, tolerância a falhas, retenção de dados e escalabilidade horizontal. Isso aumenta a complexidade arquitetural do Kafka.

2. Alta Disponibilidade e Desempenho 

NATS 

Todos os nós em um cluster estão interconectados em uma malha, e o cliente pode se conectar a qualquer nó. Essa configuração evita um único ponto de falha. Se um nó falhar, o cliente é conectado automaticamente aos outros nós sem intervenção manual. Isso é chamado de auto-recuperação no NATS. Um nó habilitado para JetStream distribui os fluxos entre todos os nós. Os fluxos são altamente gerenciados e balanceados entre os nós habilitados para JetStream dentro de um cluster de malha. 

O JetStream também suporta espelhamento de dados em vários clusters ou nós. No JetStream, líderes são eleitos por fluxo. A replicação de cada fluxo pode ser configurada. Todas essas coisas garantem durabilidade e disponibilidade no NATS.

Kafka

A alta disponibilidade do Kafka é baseada na replicação. Cada tópico pode ter uma ou mais partições. Cada partição é replicada entre os Brokers do Kafka. Isso garante a redundância e a disponibilidade dos dados. O Kafka segue um mecanismo de replicação Leader-Follower. Um líder cuida das leituras e gravações. E o seguidor trabalha na replicação dos dados.

O Kafka mantém algo chamado ISR (In Sync Replicas) para cada partição. Se o líder falhar, um dos ISRs se torna o líder. Para gerenciamento de metadados do cluster e eleição de líderes, o Kafka depende do Zookeeper (KRaft nas versões mais recentes).

Performance and Scalability
Recurso
NATS
Kafka
Taxa de Transferência
Alta ou baixa latência. Otimizado para mensagens pequenas
Otimizado para alta taxa de transferência e mensagens grandes
Escalabilidade
Escalável horizontalmente com clustering
Escalável horizontalmente com particionamento
Latência
Menos de um milissegundo
Milissegundos
Recovery and FAILOver
Recurso
NATS
Kafka
Tempo de Falha
Sub-segundo (Reconexão do Cliente mais Rápida)
Mais Lento (Depende do Processo de Eleição do Líder)
Recuperação sem Interrupções
Clientes se reconectam automaticamente sem interrupção
Algum tempo de inatividade durante a eleição do líder
Risco de Perda de Dados
Mínimo com replicação (JetStream)
Mínimo se a replicação e ISR estiverem configurados

3. Padrões de Mensagem

NATS

O NATS utiliza mensagens baseadas em assunto. Isso permite que serviços e fluxos usem padrões de Pub-Sub, Solicitação-Resposta e Assinante de Fila. Os assuntos no NATS podem ser construídos com hierarquia e curingas. Um único fluxo NATS pode armazenar vários assuntos e os aplicativos do cliente podem usar filtragem no lado do servidor para receber apenas os assuntos de interesse. A conexão no NATS é bidirecional e permite que os clientes publiquem e se inscrevam ao mesmo tempo. O NATS também suporta Filas muito semelhantes ao RabbitMQ.

Kafka

Os Streams no Kafka suportam mensagens de Pub-Sub e baseadas em tópicos. O balanceamento de carga pode ser alcançado por meio de grupos de Consumidores e particionamento dos tópicos.

4. Garantias de Entrega

NATS

O NATS suporta várias garantias de entrega. O NATS sozinho pode suportar uma garantia de entrega no máximo uma vez. Os servidores NATS com JetStream habilitado podem suportar mais dois tipos de garantias. São as garantias “pelo menos uma vez” e “exatamente uma vez”. O NATS pode enviar ‘acks’ para mensagens individuais. Consulte a documentação oficial do NATS para os vários ‘acks’ que ele suporta. Com base no tipo de ‘acks’, o NATS pode reenviar mensagens.

Kafka

O Kafka suporta garantias pelo menos uma vez e exatamente uma vez. A ordenação de mensagens é garantida no nível da Partição. A ordenação global não é possível no Kafka.

5. Retenção e Persistência de Mensagens

NATS

O NATS suporta persistência em memória e baseada em arquivos. Existem várias opções para reproduzir a mensagem. A reprodução de mensagens pode ser por tempo, contagem ou número de sequência.

Kafka

O KAFKA suporta apenas persistência baseada em arquivos. As mensagens podem ser reproduzidas a partir do último, do mais antigo ou de um offset específico. A Compactação de Log é suportada no KAFKA.

6. Idiomas e Plataforma

NATS

Quarenta e oito tipos de clientes conhecidos. Qualquer arquitetura que suporte GOLANG pode suportar servidores NATS.

Kafka

Dezoito tipos de clientes conhecidos. Servidores Kafka podem ser executados em plataformas que suportam JVM.

Casos de Uso

Caso de Uso 1

Requisitos

Temos uma plataforma de dados com um pipeline de streaming. A plataforma usa o motor Apache Flink para streaming em tempo real e o Apache Beam para escrever o pipeline de análise. Abaixo estão os principais requisitos:

  1. Processamento de mensagens com alto rendimento e baixa latência
  2. Suporte para checkpoint e tratamento de contra pressão
  3. Manuseio de mensagens em MB
  4. Durabilidade e persistência de mensagens

Comparação

Vantagens do Kafkas:

  • Alto rendimento
  • Retenção de dados com políticas de retenção configuráveis e replicação de dados para tolerância a falhas
  • Suporte para pelo menos uma garantia de entrega de mensagem
  • Leitura de mensagens a partir de offsets mais antigos/mais recentes/específicos
  • ‘Acks’ do lado do servidor para entrega confiável
  • Manuseio de grandes fluxos de dados e mensagens de grande tamanho
  • Suporte para Tópico de Compactação

Desvantagens do Kafka:

  • Alto uso de recursos. Nosso cluster era local e com recursos limitados
  • Kafka é apenas quase em tempo real

Vantagens do NATS:

  • Alto desempenho com uso mínimo de recursos. O nosso é um cluster local com restrições de recursos
  • Suporte para pelo menos uma vez. Estávamos procurando uma garantia de pelo menos uma vez
  • Processamento de mensagens com baixa latência

Desvantagens do NATS:

  • Sem conectores para Flink/Beam, portanto, a integração era difícil
  • Redução de desempenho com o tamanho da mensagem

Decisão Final

Após uma análise cuidadosa, o Kafka foi escolhido. Tivemos que fazer um compromisso entre o uso de recursos e os outros benefícios que o Kafka oferecia, especialmente a boa integração disponível com Apache Beam e Flink. Outra vantagem do Kafka era seu manuseio de grandes tamanhos de mensagem e processamento de mensagens de alto throughput.

Caso de Uso 2

Requisitos

Gerenciar os eventos gerados em um cluster local, Ex: Logs de Auditoria. Os eventos devem ser processados com baixa latência. E suportar a comunicação entre microserviços. Durabilidade e persistência não eram um requisito. O tamanho da mensagem era pequeno. Não havia necessidade de fazer análises sobre os eventos. Estávamos em um ambiente restrito. O uso de recursos e a pegada de memória devem ser mínimos.

Decisão

Por que o NATS foi escolhido:

  • Uso eficiente de recursos
  • Manuseio de eventos com baixa latência.
  • Uma vez que é uma aplicação Go, a pegada de memória é muito baixa
  • Capacidade de lidar com tamanhos pequenos de mensagens 
  • Suporte de Solicitação-Resposta que pode auxiliar na comunicação de Microsserviços
  • Quando o JetStream não está configurado, as mensagens não são armazenadas

Por que o Kafka não foi escolhido:

  • Por padrão, as mensagens são armazenadas em disco
  • O uso de recursos é alto em comparação com o NATS
  • Uma vez que necessita do JVM, a pegada de memória é muito alta

Resumo

A escolha entre Kafka e NATS depende dos requisitos específicos em três áreas-chave: Arquitetura e Complexidade, Desempenho e Escalabilidade, e Garantias de Entrega de Mensagens. Kafka é ideal para sistemas que requerem streaming de eventos robusto, armazenamento durável e capacidades avançadas de processamento, mas vem com maior complexidade. Já o NATS é leve, fácil de gerenciar, e se destaca em cenários de baixa latência e alto rendimento com necessidades de mensagens mais simples.

Ao projetar um sistema de mensagens distribuído, avalie cuidadosamente essas áreas para alinhar sua escolha com os objetivos e restrições de sua aplicação. Tanto o Kafka quanto o NATS são ferramentas poderosas, e a escolha certa dependerá do seu caso de uso.

Áreas-chave a serem consideradas antes de escolher entre Kafka e NATS:

  1. Arquitetura e complexidade
  2. Alta disponibilidade e desempenho
  3. Garantias de entrega de mensagens

Kafka é ideal para sistemas distribuídos que requerem streaming de eventos, armazenamento durável e capacidades avançadas de processamento. No entanto, o Kafka vem com alto uso de recursos e uma pegada de memória. E a complexidade de gerenciamento é muito alta em comparação com o NATS.

Por outro lado, o NATS é leve e fácil de gerenciar. O processamento de mensagens de baixa latência é a capacidade de assinatura do NATS.

Em última análise, tanto o Kafka quanto o NATS são ferramentas poderosas para lidar com eventos. A escolha depende de casos de uso específicos.

Source:
https://dzone.com/articles/kafka-vs-nats-message-processing