Você já ouviu que o Kafka é "durável e tolerante a falhas". Mas você sabe exatamente como ele evita a perda de mensagens?

Vou explicar do básico ao avançado.


Primeiro, a estrutura

Antes de falar em durabilidade, você precisa entender 4 conceitos:

  • Broker: um servidor Kafka. Em produção, você tem um cluster com vários brokers.
  • Topic: canal de mensagens, dividido em partitions.
  • Partition: unidade de armazenamento. Um log imutável e append-only.
  • Replica: cópia de uma partition em outro broker.

Como funciona a replicação?

O Kafka usa o modelo Leader-Follower:

  • Cada partition tem 1 leader e N followers.
  • Só o leader recebe escritas.
  • Os followers fazem fetch contínuo do leader (pull, não push).
  • As replicas sincronizadas formam o ISR (In-Sync Replicas).

Se um follower fica mais de ~10s sem replicar, ele sai do ISR. Quando se recupera, precisa re-sincronizar antes de voltar.


O conceito mais importante: High Watermark

O High Watermark (HW) é o offset até o qual todas as replicas do ISR já confirmaram a escrita.

Consumers só enxergam mensagens abaixo do HW.

Isso garante que nenhum consumer leia uma mensagem que ainda não foi replicada e que poderia sumir em caso de falha do leader.


ACKs: a configuração que muda tudo

Quando um producer envia uma mensagem, ele escolhe o nível de confirmação:

  • acks=0: manda e esquece. Zero garantia.
  • acks=1: leader confirma. Se ele cair antes de replicar, a mensagem se perde.
  • acks=all: leader só confirma depois que todo o ISR confirmou. Máxima durabilidade.

Em produção: use acks=all.


Mas acks=all não é suficiente sozinho

Se o ISR tiver apenas 1 replica (o próprio leader), acks=all vira acks=1 na prática.

Por isso existe o min.insync.replicas:

  • Define o mínimo de replicas no ISR para aceitar uma escrita.
  • Se cair abaixo disso, o Kafka rejeita com NotEnoughReplicasException.

Combinação recomendada para produção:

  • replication.factor=3
  • min.insync.replicas=2
  • acks=all

Tradução: "aguenta 1 broker fora do ar, sem perder dados."


E a durabilidade em disco?

As mensagens ficam primeiro no page cache do sistema operacional antes de serem escritas no disco.

Você pode forçar o flush com:

  • log.flush.interval.messages
  • log.flush.interval.ms

Na prática, a maioria das equipes não configura flush agressivo e confia na replicação. Com 3 replicas, a chance de todas perderem o page cache ao mesmo tempo é quase zero, mas você precisa entender esse tradeoff.


O que acontece quando o leader cai?

  • O Controller (KRaft, antes ZooKeeper) detecta a falha.
  • Elege um novo leader dentre as replicas do ISR.
  • O novo leader começa a aceitar escritas.
  • Replicas desatualizadas truncam mensagens acima do HW e re-sincronizam.

Atenção: unclean.leader.election.enable=true permite eleger uma replica fora do ISR. Isso garante disponibilidade, mas causa perda de dados. Mantenha como false em produção.


E o producer?

  • retries + delivery.timeout.ms: o producer retenta automaticamente em falhas transientes.
  • enable.idempotence=true: evita duplicatas nas retentativas. O broker rastreia o sequence number por producer.
  • Transações Kafka: para atomicidade entre múltiplas partitions ou em fluxos consume + produce.

Resumo: níveis de garantia

  • acks=0: durabilidade nenhuma, performance máxima, risco de perda certo.
  • acks=1: durabilidade parcial, performance alta, risco de perda possível.
  • acks=all + min.insync.replicas=1: durabilidade parcial, performance alta, risco de perda possível.
  • acks=all + min.insync.replicas=2 + replication.factor=3: durabilidade alta, performance boa, risco minimo.
  • acks=all + min.insync.replicas=2 + replication.factor=3 + enable.idempotence=true: durabilidade maxima, performance boa, sem duplicatas por retentativa.

TL;DR

A durabilidade no Kafka nao e magica: e uma combinacao de decisoes conscientes.

  • Replicacao Leader-Follower com ISR
  • High Watermark para controle de visibilidade
  • acks=all + min.insync.replicas para garantia de escrita
  • Producer idempotente para evitar duplicatas
  • Eleicao de leader segura (unclean.leader.election.enable=false)

Nenhum mecanismo isolado e suficiente. A durabilidade no Kafka e configurada, nao herdada.