---
title: "Kafka Simulator v1.1: Entendendo a Semântica do Produtor no Kafka"
date: 2026-07-14T00:00:00.000Z
author: "michal"
excerpt: "O Kafka Simulator v1.1 adiciona dez cenários que cobrem batching do produtor, particionamento, compressão, backpressure, retentativas e idempotência."
---
O que acontece depois que um produtor Kafka chama `send()`?

Isso parece uma pergunta simples. O produtor cria um registro, envia-o ao Kafka e recebe uma confirmação.

No entanto, muita coisa pode acontecer entre esses passos.

O produtor pode esperar por mais registros e criar um batch. Ele precisa escolher uma partição. Ele pode comprimir o batch. Se o broker estiver lento, o produtor pode ficar sem espaço no buffer. Se uma requisição falhar, ele pode tentá-la novamente. Se a retentativa for bem-sucedida depois que a primeira requisição já foi escrita, o Kafka pode receber o mesmo batch duas vezes.

O [Kafka Simulator](/kafka-simulator/) v1.1 foca nessa semântica do produtor.

A versão adiciona **10 novos cenários**, elevando o currículo completo para **23 de 125 cenários**.

## O que está incluído na v1.1?

Oito dos dez cenários focam no produtor. Os outros dois estendem a trilha de anatomia do log: a leitura até o high watermark e o log start offset.

Os cenários do produtor cobrem cinco áreas:

- batching com `linger.ms` e `batch.size`,
- particionadores do produtor,
- compressão,
- backpressure com `buffer.memory` e `max.block.ms`,
- retentativas e idempotência.

Vamos analisar cada uma delas.

## Batching com `linger.ms` e `batch.size`

Um produtor Kafka não envia necessariamente cada registro em uma requisição separada.

Registros atribuídos à mesma partição podem ser reunidos em um batch. O produtor envia o batch quando ele fica cheio ou quando o tempo de espera configurado expira.

É aqui que duas configurações do produtor se tornam importantes:

- `batch.size` limita o tamanho de um batch,
- `linger.ms` permite que o produtor espere por registros adicionais antes de enviá-lo.

O compromisso é entre latência e vazão.

Um batch maior geralmente significa menos requisições e melhor compressão. No entanto, esperar o batch encher pode aumentar a latência de um registro individual.

Os novos cenários tornam esse comportamento visível. Você pode ver quando os registros entram em um batch, o que faz o batch ser enviado e como alterar a configuração afeta as requisições produzidas pelo cliente.

## Particionadores do produtor

Antes que o produtor possa criar um batch específico de partição, ele precisa selecionar uma partição.

Para registros com chave, a chave é usada para escolher a partição. Registros com a mesma chave são, portanto, normalmente atribuídos à mesma partição.

Para registros sem chave, o comportamento é diferente. O produtor pode agrupar registros usando sua estratégia de particionamento em vez de calcular a partição a partir de uma chave.

O simulador mostra ambos os casos passo a passo:

1. o produtor recebe o registro,
2. o particionador seleciona uma partição,
3. o registro é adicionado ao batch correspondente,
4. o batch é enviado ao líder daquela partição.

Isso facilita entender por que o particionamento afeta tanto a ordenação quanto o batching.

## A compressão acontece por batch

A compressão do produtor Kafka é aplicada a batches de registros, não de forma independente a cada registro.

Essa distinção importa.

A compressão costuma ser mais eficaz quando um batch contém múltiplos registros semelhantes. Um batch que contém apenas um registro pequeno pode ganhar muito pouco com a compressão. Um batch maior com dados repetitivos pode ser comprimido de forma muito mais eficiente.

Como resultado, a compressão está conectada à configuração de batching. Configurações como `batch.size` e `linger.ms` podem influenciar não só a frequência das requisições, mas também o formato e a compressibilidade dos batches resultantes.

Os novos cenários mostram os tamanhos dos batches não comprimidos e comprimidos, tornando essa relação explícita.

## Backpressure com `buffer.memory` e `max.block.ms`

O que acontece quando uma aplicação produz registros mais rápido do que o Kafka consegue aceitá-los?

O produtor não pode manter um número ilimitado de registros não enviados na memória. Ele usa um buffer limitado, configurado por meio de `buffer.memory`.

Quando o buffer não tem espaço disponível, uma chamada a `send()` pode bloquear enquanto espera que memória seja liberada.

Ela não esperará para sempre. O tempo máximo de bloqueio é controlado por `max.block.ms`.

Isso nos dá dois resultados possíveis:

- dados suficientes são enviados e confirmados, liberando espaço no buffer,
- nenhum espaço fica disponível antes do timeout, e o envio falha.

O simulador acompanha o buffer do produtor diretamente. Você pode ver a memória sendo alocada quando registros são adicionados e liberada conforme as requisições são concluídas.

Isso é especialmente útil quando combinado com um broker lento ou uma quota de vazão. Em vez de tratar o backpressure do produtor como uma questão abstrata de configuração, você pode observar o buffer encher e ver exatamente qual envio fica bloqueado.

## Retentativas e o problema das duplicatas

Suponha que o produtor envie um batch a um broker.

O broker escreve o batch com sucesso, mas a confirmação é perdida antes de chegar ao produtor.

Do ponto de vista do produtor, a requisição falhou. Ele não tem como saber se o broker escreveu os dados. Tentar novamente é, portanto, razoável.

No entanto, se a primeira requisição foi escrita com sucesso, a retentativa pode acrescentar o mesmo batch novamente.

Esse é o problema das duplicatas causado por falhas ambíguas.

O cenário de retentativa mostra ambas as requisições:

1. a requisição original chega ao broker,
2. a confirmação é perdida,
3. o produtor tenta o batch novamente,
4. o broker recebe os mesmos registros pela segunda vez.

Sem idempotência, ambas as cópias podem ser acrescentadas.

## Semântica do produtor idempotente

Um produtor idempotente permite que o Kafka reconheça batches retransmitidos.

O Kafka atribui uma identidade ao produtor e rastreia números de sequência de forma independente para cada partição. Quando um batch é retransmitido com um número de sequência que o broker já processou, o broker pode confirmá-lo sem acrescentar os registros novamente.

A distinção importante é entre uma retentativa e uma duplicata genuína.

Dois registros podem conter exatamente a mesma chave e o mesmo valor e ainda assim serem dois registros separados enviados intencionalmente pela aplicação. O Kafka não deve remover esses registros.

A idempotência deduplica retentativas do protocolo do produtor. Ela não deduplica os dados da aplicação com base em seu conteúdo.

Os novos cenários mostram:

- IDs de produtor,
- números de sequência por partição,
- retentativas idempotentes bem-sucedidas,
- registros duplicados genuínos,
- detecção de sequência fora de ordem.

## Por que `max.in.flight.requests.per.connection` importa?

Um produtor pode ter várias requisições aguardando respostas ao mesmo tempo.

Isso melhora a vazão, mas também cria um possível problema de ordenação.

Suponha que o produtor envie o batch A e depois o batch B. O batch A falha temporariamente, enquanto o batch B tem sucesso. Se A for retransmitido depois que B já foi escrito, os registros podem ser acrescentados em uma ordem diferente.

A idempotência usa números de sequência para detectar ordenação inválida.

O simulador mostra isso explicitamente. Você pode ver o número de sequência esperado pelo broker, o número carregado pelo batch que chega e o ponto em que o broker rejeita uma requisição fora de ordem.

## Inspecionando o estado interno do produtor

Os novos cenários se apoiam fortemente no **inspetor** do simulador, que expõe o estado interno de produtores e partições, incluindo:

- contadores de retentativa,
- números de sequência do produtor,
- números de sequência do broker,
- alocação de buffer.

Normalmente, esses valores ficam escondidos por trás de métricas do produtor, logs e comportamento de protocolo. No simulador, eles podem ser inspecionados diretamente enquanto você avança ou retrocede em um cenário.

## Correções no modelo do produtor

Adicionar os novos cenários também exigiu tornar o modelo de produtor existente mais preciso.

### As retentativas são contadas por batch

O Kafka retransmite requisições de produção que contêm batches de registros.

Uma requisição que falha deve, portanto, consumir uma retentativa para o batch completo, não uma retentativa para cada registro dentro dele.

O simulador agora segue esse modelo. Cada registro de um batch que falhou é enviado novamente, enquanto o contador de retentativas avança uma única vez.

### A memória do buffer é liberada com precisão

A memória do buffer do produtor agora é liberada conforme as confirmações chegam.

Isso corrige casos em que o simulador podia reportar backpressure mesmo que registros confirmados já devessem ter liberado sua memória.

O mesmo se aplica aos timeouts de `max.block.ms`. Quando um envio bloqueado expira, sua alocação de buffer é limpa.

### `acks=all` é rastreado por partição

A durabilidade do Kafka é definida de forma independente para cada partição.

Um produtor que escreve em várias partições precisa, portanto, esperar que a partição correta satisfaça seus requisitos de confirmação. O progresso em outra partição não deve confirmar uma requisição não relacionada.

O simulador agora rastreia esse estado separadamente para cada partição e tópico.

### O reset do produtor limpa o estado de idempotência

O broker armazena o estado de deduplicação associado a um produtor idempotente.

Quando um produtor simulado é removido ou resetado, esse estado também precisa ser removido. Caso contrário, um produtor recém-criado pode ter seus registros classificados incorretamente como retentativas antigas.

O comportamento de reset agora limpa o estado correspondente no lado do broker.

### Retroceder restaura o estado de retentativa

Os cenários podem ser avançados e retrocedidos um passo de cada vez.

Retroceder agora reconstrói os contadores de retentativa usados durante cada rodada de simulação. O estado visível do produtor é, portanto, consistente, independentemente de o cenário estar avançando ou retrocedendo.

## Melhorias no playground

A versão também contém várias correções fora do modelo do produtor.

### Rebalanceamento de grupos de consumidores

Os grupos de consumidores no playground receberam várias correções de corretude:

- o sticky assignor agora minimiza a movimentação de partições em vez de reatribuir tudo do zero,
- um membro estático que fica ausente por mais tempo que `session.timeout.ms` é removido como qualquer outro membro,
- alterar a contagem de partições de um tópico agora dispara um rebalanceamento adequado sem perturbar o estado dos membros,
- partições nunca são atribuídas a um membro que não está mais vivo.

### Configuração de tópicos e compactação

O Kafka nunca reduz a contagem de partições de um tópico. Encolher apagaria dados e quebraria o particionamento baseado em chave, então `kafka-topics --alter` rejeita a operação com `InvalidPartitionsException`.

O playground agora segue a mesma regra. Uma redução na contagem de partições é rejeitada com um erro didático em vez de descartar partições silenciosamente.

Tópicos compactados também se comportam com mais precisão:

- um tombstone sobrevive até que sua própria janela de carência de `delete.retention.ms` expire,
- um registro sem chave não pode ser produzido em um tópico compactado,
- com `compact,delete`, a retenção por tempo agora recupera registros antigos independentemente da compactação.

### Os links de compartilhamento preservam o cenário completo

O playground serializa suas ações na URL para que um cenário possa ser compartilhado com outra pessoa.

O codec agora inclui todas as mudanças de configuração, incluindo atualizações na contagem de partições. Um link que solicita um tipo de cluster de um pacote de lançamento posterior agora recorre a uma topologia suportada em vez de renderizar um cluster inutilizável.

Abrir um link compartilhado deve, portanto, recriar o mesmo cenário que foi originalmente construído.

### Correções de interação

Vários problemas menores do playground também foram corrigidos:

- identificadores de entidade não colidem mais depois que uma entidade é removida e recriada,
- o posicionamento de produtores funciona corretamente em grades de broker mais largas.

### Cabeçalhos de segurança

O site agora envia uma Content Security Policy e uma Permissions Policy.

## Por que começar pelo produtor?

As garantias do Kafka costumam ser discutidas do ponto de vista do broker: replicação, participação no ISR, high watermarks e failover de líder.

No entanto, a garantia observada por uma aplicação também depende do produtor.

Qual modo de confirmação ele usa? Ele tenta novamente? A idempotência está ativada? Quantas requisições podem estar em voo? O que acontece quando seu buffer local fica cheio?

Essas configurações determinam se uma escrita é rápida, durável, ordenada, duplicada, bloqueada ou rejeitada.

É por isso que o primeiro pacote maior de cenários do Kafka Simulator foca no produtor.

Uma vez que batching, confirmações, retentativas e idempotência ficam visíveis, os cenários posteriores que cobrem replicação, durabilidade e transações têm uma base mais clara.

Abra o [Kafka Simulator](/kafka-simulator/), selecione a trilha do produtor e experimente os cenários de falha passo a passo.