Perda de Mensagens
Cenários onde uma mensagem some:
- Producer envia mas não confirmou recebimento e crashou. → mensagem nunca foi pro Kafka.
- Kafka recebe mas não replicou e o broker líder caiu. → perdida.
- Consumer "comitou" o offset antes de processar e crashou. → próximo consumer pula essa mensagem.
Garantias de Entrega
Existem 3 níveis:
| Garantia | Comportamento | Quando usar |
|---|---|---|
| At-most-once | Pode perder, nunca duplica | Métricas onde perder um ponto não doi |
| At-least-once | Nunca perde, pode duplicar | Padrão, com consumers idempotentes |
| Exactly-once | Nunca perde, nunca duplica (caro) | Transações financeiras críticas |
Como configurar at-least-once no producer?
acks=all → espera todas as réplicas confirmarem
retries=Integer.MAX → tenta indefinidamente
enable.idempotence=true → evita duplicação por retry do producer
No consumer, processe antes de comitar offset:
for {
msg := readMessage()
err := processMessage(msg) // 1. processa
if err == nil {
commitOffset(msg) // 2. só depois comita
}
}Duplicidade
Se você usa at-least-once (e provavelmente é o seu caso), mensagens vão duplicar em algum momento. Cenários:
- Consumer processou mas crashou antes de comitar offset → outro consumer reprocessa.
- Producer fez retry de uma mensagem que já tinha sido enviada.
- Rebalanceamento de partições durante deploy.
Solução: idempotência (veja o capítulo anterior). É inevitável, prepare-se.
Ordem dos Eventos
A ordem só é garantida dentro de uma partição. Se você publica eventos sem key, eles se espalham entre partições e a ordem se perde.
Cenário problemático:
Eventos do pedido 123:
T=1: PedidoCriado → vai pra partição 0
T=2: PagamentoAprovado → vai pra partição 2
T=3: PedidoEnviado → vai pra partição 1
O consumer que lê a partição 1 pode receber PedidoEnviado antes do PedidoCriado aparecer. Caos.
Solução: use uma chave consistente. Exemplo: pedidoId como key. Assim, todos os eventos de um mesmo pedido vão pra mesma partição e mantêm a ordem.
Eventos do pedido 123 (todos com key="123"):
T=1: PedidoCriado → partição 0
T=2: PagamentoAprovado → partição 0
T=3: PedidoEnviado → partição 0
(ordem garantida)