O volume sobe, o lag começa a aparecer e a reação imediata parece óbvia: adicionar mais consumers ao grupo.
Em muitos ambientes de produção, é exatamente nesse momento que o comportamento fica estranho.
Novas instâncias entram, o consumo oscila, alguns gráficos parecem "congelar" por instantes e o throughput perde estabilidade.
Em vez de acelerar o fluxo, a escala passa a introduzir pausas. O nome desse efeito é rebalance.
No post sobre lag alto, esse sintoma já apareceu como causa recorrente de atraso. Aqui, vale isolar o fenômeno: o rebalance, por si só, já consegue degradar um consumer group sob carga.
O que está acontecendo de verdade
Um consumer group é o mecanismo que permite que vários consumers trabalhem juntos lendo o mesmo tópico de forma paralela.
Nesse modelo, as partitions são divididas entre os membros do grupo.
Cada partition fica atribuída a apenas um consumer daquele group por vez. É isso que evita processamento concorrente da mesma partition e cria o paralelismo controlado do consumo.
Quando um novo consumer entra, quando outro sai ou quando a topologia muda, o grupo precisa recalcular essa distribuição.
As partitions são redistribuídas entre os consumers ativos para que a leitura continue consistente.
Esse processo de reorganização é o rebalance.
Essa escolha não é randômica. O Kafka aplica uma estratégia de atribuição para decidir como as partitions serão distribuídas entre os membros do grupo, buscando equilíbrio e consistência na divisão do trabalho.
Na prática, algumas estratégias conhecidas fazem isso de formas diferentes:
Range: distribui partitions por tópicoRoundRobin: tenta espalhar as partitions de forma mais uniforme entre os consumersSticky: tenta equilibrar a carga movendo o mínimo possível de partitionsCooperativeSticky: segue a ideia doSticky, mas reduz o impacto da redistribuição
Um exemplo simples ajuda a visualizar.
Imagine um tópico com 6 partitions e um consumer group com 3 consumers. Nesse cenário, cada consumer pode ficar responsável por 2 partitions.
Se uma nova instância entra no grupo, a distribuição anterior deixa de fazer sentido. O Kafka precisa redistribuir as 6 partitions entre 4 consumers, talvez deixando alguns com 2 partitions e outros com 1.
O mesmo vale no sentido contrário. Se um dos 3 consumers sai ou falha, as partitions que estavam com ele precisam ser reassumidas pelos consumidores restantes.
Em ambos os casos, o grupo precisa parar, recalcular a divisão e retomar o consumo com a nova atribuição.
Por que o consumo pausa durante o rebalance
O rebalance não é só uma troca de ownership "em segundo plano".
Durante esse processo, os consumers precisam interromper temporariamente a leitura para que o grupo redefina quem será responsável por cada partition.
Na prática, o fluxo de consumo sofre uma pausa curta, mas real.
Se isso acontece em um sistema já pressionado por volume, essa pausa aparece rapidamente em produção:
- o lag sobe porque novas mensagens continuam chegando
- o throughput oscila porque o consumo deixa de ser contínuo
- a latência aumenta porque parte das mensagens espera a redistribuição terminar
Ou seja: adicionar consumers pode melhorar a capacidade total, mas também pode introduzir um custo operacional imediato.
Escala, aqui, não é linear.
Situações comuns que disparam rebalance
Existem alguns gatilhos clássicos.
O primeiro é subir ou derrubar instâncias de consumers. Sempre que a composição do group muda, a redistribuição das partitions precisa acontecer.
O segundo é timeout de processamento. Se um consumer demora mais do que o esperado para responder dentro das janelas de controle do grupo, ele pode ser tratado como indisponível. O resultado é o mesmo: rebalance.
O terceiro é mudança no número de partitions do tópico. Como a quantidade de trabalho disponível mudou, o group precisa reorganizar a distribuição.
Em produção, esses eventos nem sempre aparecem como falha explícita.
Muitas vezes, o sintoma percebido é só "o consumo ficou instável".
O impacto real em produção
O primeiro impacto costuma ser aumento de lag.
Mesmo pausas curtas podem acumular rapidamente quando o volume de entrada continua alto. Se rebalances acontecem em sequência, o backlog cresce antes que o grupo recupere ritmo.
O segundo impacto é a instabilidade no throughput.
Em vez de um consumo previsível, o sistema alterna entre momentos de processamento forte e pequenos intervalos de reorganização. Para quem observa o comportamento externo, parece um consumo irregular.
O terceiro impacto é a redistribuição desigual de carga.
Adicionar consumers não garante, por si só, melhor aproveitamento. Dependendo da quantidade de partitions e da forma como a carga está distribuída, alguns consumers podem receber pouco trabalho enquanto outros continuam pressionados.
Também vale separar duas discussões que costumam se misturar. Ter menos consumers do que partitions não é, por si só, um problema. Nesse caso, um mesmo consumer assume mais de uma partition, o que é um cenário comum e muitas vezes saudável.
O erro está em supor que adicionar consumers sempre melhora throughput. O Kafka não faz essa distribuição de forma aleatória. Ele aplica uma estratégia de atribuição para repartir as partitions disponíveis entre os membros ativos do consumer group, tentando distribuir o trabalho dentro das regras daquele grupo.
Quando existem mais consumers do que partitions, essa conta não fecha: não há partitions suficientes para todos. Na prática, alguns consumers recebem partitions e outros ficam sem nenhuma atribuição.
Mesmo sem consumir de fato, esses membros excedentes continuam fazendo parte do grupo. Isso significa que eles entram no protocolo de coordenação, participam da formação do group e precisam ser considerados sempre que há entrada, saída ou redistribuição.
Em outras palavras: eles não aumentam a capacidade real de leitura, mas aumentam o número de participantes envolvidos no rebalance e o custo operacional dessa reorganização.
Isso cria um efeito frustrante: mais instâncias, mais custo operacional e pouca melhora prática.
Boas práticas para reduzir esse problema
A primeira é manter os consumers estáveis.
Ambientes com entradas e saídas frequentes de instâncias tendem a provocar mais rebalances e mais interrupções no fluxo.
A segunda é planejar o paralelismo antes de escalar.
Isso não significa manter sempre menos consumers do que partitions como regra fixa. Significa entender quantas partitions existem, quanto trabalho cada consumer consegue processar e qual paralelismo o sistema realmente precisa.
Como vimos no post sobre número de partitions, escala saudável começa no desenho do consumo, não na reação ao incidente.
Ter menos consumers do que partitions pode ser perfeitamente aceitável. Já ter mais consumers do que partitions não aumenta o consumo real e ainda pode ampliar o custo operacional dos rebalances.
Esse cuidado vale também para configurações de concorrência por instância. Muita equipe aumenta o paralelismo interno de cada processo sem relacionar essa decisão ao número total de réplicas em execução. No fim, o group passa a ter mais consumers do que o tópico consegue ocupar de forma útil.
A terceira é configurar os timeouts de acordo com o tempo real de processamento.
Se o consumidor ainda está saudável, mas a configuração faz o grupo entendê-lo como ausente, o sistema cria rebalances desnecessários e piora um cenário que já estava sob carga.
Também é importante ter cuidado com estratégias automáticas de escala baseadas em lag. Quando os limites estão mal calibrados, um pico curto de volume pode disparar várias entradas de instâncias em sequência. O resultado pode ser um ciclo de 2 ou 3 rebalances seguidos, não porque faltava capacidade estrutural, mas porque a política de escala reagiu ao atraso sem considerar o custo de reorganizar o group.
Escalar sem desenho pode piorar o sistema
Em Kafka, escalar não é apenas subir mais instâncias.
Cada entrada ou saída de consumer pode reorganizar o grupo, pausar o consumo por um período e afetar lag, latência e throughput.
Por isso, rebalance não deve ser tratado como detalhe interno da plataforma.
Ele é parte do comportamento operacional do sistema.
Kafka entrega alto poder de escala, mas exige planejamento arquitetural e operacional.
Sem isso, a tentativa de ganhar vazão pode acabar produzindo exatamente o contrário: mais oscilação, mais atraso e menos previsibilidade. Escalar por impulso, por lag momentâneo ou por configuração mal dimensionada de concorrência costuma só acelerar a instabilidade que o sistema já estava tentando absorver.
Referência técnica
Apache Kafka:
