The Code Codex
Tema
← Guias

Kafka

Plataforma distribuída de streaming de eventos: o log, tópicos e partições, produtores e consumidores, replicação, garantias de entrega, filas com share groups, ecossistema e padrões de produção.

31 jan 2025· 10 min· 15 seções

Neste guia · 15 seções

Por que Kafka

Quando cada sistema conversa direto com os outros, cada nova integração é mais um fio, e o número de fios cresce rápido. O Kafka coloca um log de eventos central no meio: quem produz escreve uma vez, e quem precisa consome quando e quantas vezes quiser.

Com um log central

Pedidos

Kafka

Pagamentos

Faturamento

Estoque

Analytics

Integração ponto a ponto

Pedidos

Faturamento

Estoque

Analytics

Pagamentos

Com um log central

Pedidos

Kafka

Pagamentos

Faturamento

Estoque

Analytics

Integração ponto a ponto

Pedidos

Faturamento

Estoque

Analytics

Pagamentos

“Plataforma distribuída de streaming de eventos de alta performance”:

  • Alta vazão e baixa latência: milhões de mensagens por segundo num cluster.
  • Escalável horizontalmente: mais brokers, mais partições.
  • Armazenamento: as mensagens não somem ao serem lidas; ficam pelo tempo configurado.
  • Alta disponibilidade, por replicação entre máquinas.
  • Conectividade: conectores e bibliotecas prontas para quase tudo.

O log: a ideia central

Cada partição de um tópico é um log: uma sequência de mensagens que só cresce no final. Cada mensagem recebe um número sequencial, o offset. Consumidores não apagam nada; cada um só guarda até onde já leu.

0

1

2

3

4

5

6

↑ Analytics

leu até o 2

↑ Faturamento

leu até o 5

↑ Produtor

escreve aqui

0

1

2

3

4

5

6

↑ Analytics

leu até o 2

↑ Faturamento

leu até o 5

↑ Produtor

escreve aqui

Por isso dois consumidores podem estar em pontos diferentes do mesmo log, um consumidor novo pode ler tudo desde o começo e, depois de corrigir um bug, dá para voltar o offset e reprocessar.

Laboratório: Kafka local em dois minutos

Com Docker, um broker de verdade (já em modo KRaft) sobe com um comando:

Terminal window
docker run -d --name kafka -p 9092:9092 apache/kafka:4.2.2

Os scripts de linha de comando ficam em /opt/kafka/bin dentro do container:

Terminal window
# cria um tópico com 3 partições
docker exec -it kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 \
--create --topic pedidos --partitions 3
# terminal 1: produz mensagens no formato chave:valor
docker exec -it kafka /opt/kafka/bin/kafka-console-producer.sh --bootstrap-server localhost:9092 \
--topic pedidos --property parse.key=true --property key.separator=:
# terminal 2: consome desde o início, mostrando chave e partição
docker exec -it kafka /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
--topic pedidos --from-beginning --property print.key=true --property print.partition=true

Envie pedido-42:criado, pedido-7:criado e pedido-42:pago: os dois eventos do pedido 42 sempre caem na mesma partição.

Arquitetura do cluster

  • Broker: um servidor Kafka. Guarda em disco as partições pelas quais é responsável e atende produtores e consumidores.
  • Cluster: um conjunto de brokers. Em produção, no mínimo 3, para tolerar a queda de um.
  • KRaft: o protocolo de consenso com que os próprios brokers (ou nós dedicados, os controllers) mantêm os metadados do cluster: quais tópicos existem, quem lidera cada partição, quais brokers estão vivos. Substituiu o ZooKeeper, que foi removido no Kafka 4.0.

Tópicos, partições e chaves

Um tópico é um canal com nome (pedidos, pagamentos). Ele é dividido em partições, espalhadas pelos brokers, que distribuem a carga e aumentam a vazão. A ordem só é garantida dentro de cada partição.

Cada mensagem tem:

  • Key: decide a partição (por hash). Mesma chave, mesma partição, ordem garantida entre elas. Sem chave, as mensagens são distribuídas entre as partições.
  • Value: o conteúdo (JSON, Avro, Protobuf).
  • Headers: metadados (trace id, versão do schema).
  • Timestamp.
Quantas partições?

A quantidade de partições é o teto de paralelismo de um consumer group. Dá para aumentar depois, mas não diminuir, e aumentar muda para qual partição cada chave vai, quebrando a ordem durante a transição. Comece com folga (ex.: 6 ou 12 para um tópico com tráfego relevante).

Retenção e compactação
  • Por tempo ou tamanho (retention.ms, padrão de 7 dias): mensagens antigas são apagadas, tenham sido lidas ou não.
  • Compactação (cleanup.policy=compact): mantém só a última mensagem de cada chave. Transforma o tópico numa tabela com o estado atual (ex.: o endereço mais recente de cada cliente).

Produtores

O produtor escolhe quanta confirmação espera com acks:

acksConfirmaçãoRisco
0Nenhuma: envia e seguePode perder mensagens sem saber
1O líder gravouPerde se o líder cair antes de replicar
all (ou -1)Todas as réplicas em dia (ISR) gravaramO mais seguro; padrão desde o Kafka 3.0

Desde o 3.0, o produtor também é idempotente por padrão: retries de rede não geram mensagens duplicadas nem fora de ordem na partição. Para vazão, ele agrupa mensagens em lotes (linger.ms, batch.size) e pode comprimi-las (compression.type=zstd).

var props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("key.serializer", StringSerializer.class.getName());
props.put("value.serializer", StringSerializer.class.getName());
try (var producer = new KafkaProducer<String, String>(props)) {
// a mesma chave garante a ordem dos eventos deste pedido
producer.send(new ProducerRecord<>("pedidos", "pedido-42", "{\"status\":\"PAGO\"}"), (meta, error) -> {
if (error != null) log.error("falha ao publicar", error);
});
}

Consumidores

Consumer groups

Consumidores com o mesmo group.id dividem as partições entre si: cada partição é lida por um consumidor do grupo. Grupos diferentes leem tudo, de forma independente.

Consumer group: faturamento

Consumer group: analytics

Tópico pedidos

key=pedido-42

key=pedido-7

Produtor

Partição 0

Partição 1

Partição 2

Consumidor C

lê as 3 partições

Consumidor A

Consumidor B

Consumer group: faturamento

Consumer group: analytics

Tópico pedidos

key=pedido-42

key=pedido-7

Produtor

Partição 0

Partição 1

Partição 2

Consumidor C

lê as 3 partições

Consumidor A

Consumidor B

Consequência: mais consumidores do que partições num grupo não aumenta a vazão; os excedentes ficam parados, de reserva.

Offsets e commit

O consumidor lê em laço (poll) e confirma (commit) até onde processou. O offset confirmado fica guardado no próprio Kafka, e é de onde o grupo continua depois de um restart.

props.put("group.id", "faturamento");
props.put("enable.auto.commit", "false"); // confirma só depois de processar
try (var consumer = new KafkaConsumer<String, String>(props)) {
consumer.subscribe(List.of("pedidos"));
while (true) {
var records = consumer.poll(Duration.ofMillis(500));
for (var record : records) {
process(record.key(), record.value());
}
consumer.commitSync();
}
}

Com Spring Boot, o laço, o commit e as threads ficam com o framework:

@KafkaListener(topics = "pedidos", groupId = "faturamento")
void onOrder(ConsumerRecord<String, String> record) {
process(record.key(), record.value());
}
Rebalance

Quando um consumidor entra, sai ou trava, o grupo redistribui as partições. Desde o Kafka 4.0 está pronto para produção um novo protocolo de rebalance (KIP-848), coordenado pelo broker, que move só as partições necessárias em vez de parar o grupo inteiro. Ele já vem ativo nos brokers, mas no cliente o padrão ainda é o protocolo clássico: para usar o novo, configure group.protocol=consumer.

Lag

Lag é a distância entre a última mensagem do tópico e o offset confirmado pelo grupo: quanto trabalho está acumulado. É a métrica mais importante de um consumidor.

Terminal window
docker exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group faturamento

Replicação

  • Fator de replicação: quantas cópias de cada partição existem no cluster, contando a principal. O comum é 3.
  • Líder: cada partição tem um líder, que recebe as escritas. As outras cópias (followers) replicam a partir dele.
  • ISR (in-sync replicas): as réplicas em dia com o líder. Se o líder cair, uma réplica do ISR assume, e o tópico continua disponível.
  • min.insync.replicas=2 com acks=all: a escrita só é confirmada se pelo menos duas cópias a tiverem. Com fator 3, o cluster tolera perder um broker sem perder dados nem parar.

Broker 3

Broker 2

Broker 1

replica

replica

Produtor

Partição 0

líder

Partição 0

follower

Partição 0

follower

Broker 3

Broker 2

Broker 1

replica

replica

Produtor

Partição 0

líder

Partição 0

follower

Partição 0

follower

Garantias de entrega

SemânticaComo aconteceEfeito
No máximo uma vezConfirma o offset antes de processarUma falha no meio perde a mensagem
Pelo menos uma vezConfirma depois de processar (o padrão recomendado)Uma falha no meio reprocessa a mensagem
Exatamente uma vezTransações do Kafka: ler, processar e escrever em outro tópico de forma atômicaSó vale dentro do Kafka; efeitos externos (e-mail, outro banco) ainda podem repetir

Na prática, use pelo menos uma vez e torne o consumidor idempotente: processar a mesma mensagem duas vezes não pode causar efeito duplicado (ex.: guardar o id do evento já processado). Veja o glossário.

Filas no Kafka: share groups

Tópicos e filas clássicas resolvem problemas diferentes:

Tópico com consumer groupFila (share group ou RabbitMQ)
DistribuiçãoUma partição inteira por consumidorMensagem a mensagem, para qualquer consumidor livre
ParalelismoLimitado ao número de partiçõesIndependente das partições
OrdemGarantida por partiçãoNão garantida
ConfirmaçãoPor offset (tudo até ali)Individual, por mensagem
Bom paraEventos, streaming, reprocessamento, ordem por chaveDistribuir tarefas entre workers

Desde o Kafka 4.2 (fevereiro de 2026), os share groups trazem a semântica de fila para dentro do Kafka. Cada mensagem é entregue a um consumidor com uma trava temporária, e ele responde:

  • ACCEPT: processou, não entrega de novo.
  • RELEASE: falha temporária, devolve para outro consumidor tentar.
  • REJECT: não dá para processar, descarta.

Se a trava expirar sem resposta, a mensagem volta para a fila, e depois de algumas tentativas (5, por padrão) é descartada, o que evita que uma mensagem com defeito fique em loop. No Java, o cliente é o KafkaShareConsumer.

Ecossistema

  • Kafka Connect: move dados entre o Kafka e outros sistemas sem código, com conectores. Combinado com o Debezium, faz CDC (change data capture): cada alteração em uma tabela do banco vira um evento.
  • Kafka Streams: biblioteca Java para processar streams (filtrar, agregar, juntar tópicos) dentro da sua aplicação.
  • Schema Registry (Confluent, fora do projeto Apache): guarda os schemas (Avro, Protobuf, JSON Schema) e impede que um produtor publique algo que quebre os consumidores.
  • Apache Flink: processamento de streams em larga escala, com estado e janelas de tempo.

Padrões em produção

  • Outbox: para publicar um evento sem risco de inconsistência com o banco, grave-o numa tabela na mesma transação e deixe outro processo publicá-lo. Veja a nota Transactional Outbox.
  • Retry e dead letter topic: uma mensagem que falha não pode travar a partição. Envie para um tópico de retry com atraso e, depois de N tentativas, para um dead letter topic, com alerta.
  • Consumidores idempotentes: assuma que toda mensagem pode chegar duas vezes.
  • Monitore o lag de cada consumer group, não só a saúde dos brokers.
  • Contratos versionados: evolua os schemas de forma compatível; nunca mude o significado de um campo existente.

Quando usar

Use KafkaPrefira outra coisa
Eventos que vários sistemas precisam consumirPoucas mensagens e um único consumidor (uma fila simples basta)
Reprocessar o histórico (novo consumidor, correção de bug)Requisição e resposta síncronas (use HTTP ou gRPC)
Alto volume: logs, métricas, cliques, CDC de bancosTime pequeno sem quem opere um cluster (considere um serviço gerenciado)

Veja também: System design, CQRS e Observabilidade.

Vídeos

  • What is Apache Kafka? (Tim Berglund, Confluent): os conceitos com ótimas analogias (é o vídeo embutido no topo). É de 2019, então ainda fala do ZooKeeper, que hoje foi substituído pelo KRaft.
  • Apache Kafka in 6 minutes (James Cutajar): partições, offsets e replicação com um exemplo, bem direto.

Referências

1/15 · Por que Kafka