Späť na blog

Kafka rebalance búrky: prečo scale-out consumerov vie zhoršiť lag

Toto je jedna z najprotiintuitívnejších Kafka situácií:

  • consumer lag rastie
  • zvýšite počet consumerov 20 → 40
  • lag začne rásť ešte rýchlejšie
  • throughput padne
  • v logoch stále dokola “revoking partitions” / “rebalancing”

Ja som si to raz spôsobil sám — dobrý úmysel, zlý výsledok. Systém nedostal viac kapacity. Dostal viac rebalanceov a rebalance je pre consumption v praxi stop-the-world event.

Testované na: Apache Kafka 3.6–3.8, Java consumeri 3.6–3.8, high-throughput topic + DB-backed processing.

Incident (anonymizovaný)

Pipeline: Kafka → consumer → Postgres write. Jeden deploy omylom zvýšil per-message prácu (o jednu DB query navyše). Spracovanie spomalilo. Lag rástol.

Zvýšil som počet consumerov. Zhoršilo to:

  • DB pool začal thrashovať
  • processing time per poll rástol
  • consumeri prekračovali max.poll.interval.ms alebo nestíhali heartbeat
  • group sa začal rebalanceovať skoro nonstop
  • každý rebalance odoberal partitions, prerušoval prácu a generoval duplicity (nemali sme ešte 100% idempotenciu)

Blast radius: oneskorené spracovanie eventov + duplicity + tlak na downstream.

Constraint: potrebovali sme stabilizovať group rýchlo, nie “len pridať nody”.

Timeline

  • T-0: alert na lag; processing latency ide hore.
  • T+10m: scale-out consumerov; lag rastie rýchlejšie.
  • T+20m: v logoch časté rebalancy a revokácie partitions.
  • T+30m: kafka-consumer-groups.sh ukáže osciláciu medzi STABLE a REBALANCING.
  • T+45m: mitigácia: znížiť prácu per poll, doladiť config, zmeniť assignor, pridať static membership.
  • T+90m: group sa stabilizuje; lag začne klesať.
  • T+1d: pridáme “rebalance budgety” a idempotency guardrails.

Mechanizmus: prečo rebalance zničí throughput

Rebalance zastaví consumption

Počas rebalance sa partitions odoberú a pridelia znova. Podľa clienta/assignoru to môže byť dosť brutálne:

  • consumeri prestanú fetchovať
  • in-flight processing sa preruší alebo zopakuje
  • cache sa warmuje znova
  • commity failujú

Ak sa rebalance deje stále, efektívny čas consumptionu ide k nule.

Dva najčastejšie spúšťače

Spúšťač 1: prekročené max.poll.interval.ms
Ak appka nevolá poll() dosť často (lebo spracovanie je pomalé alebo blokované), Kafka ho vyhodí z group → rebalance.

Spúšťač 2: heartbeat/session timeout
GC pauzy, sieť, alebo preťaženie spôsobí missed heartbeats.

Scale-out to vie zhoršiť, lebo:

  • zvyšuje DB contention (spracovanie trvá dlhšie)
  • zvyšuje churn počas deployov
  • zvyšuje pravdepodobnosť, že aspoň jeden člen je v danom momente “pomalý”

Runbook: potvrďte rebalance storm

Čo skontrolovať ako prvé

  1. Consumer logy Hľadajte:
  • “Revoked partitions”
  • “Rebalance in progress”
  • “Max poll interval exceeded”
  • “Commit failed: rebalance in progress”
  1. Group state
kafka-consumer-groups.sh --bootstrap-server <broker:9092> --describe --group <group>
kafka-consumer-groups.sh --bootstrap-server <broker:9092> --describe --group <group> --members

Hľadám:

  • group nie je stabilne STABLE
  • members flappujú
  • partitions sa presúvajú stále dokola
  1. Tvar lagu “Píla” (rast → krátky pokles → rast) často sedí na rebalance loop.

Ako potvrdiť hypotézu

A. Či spracovanie blokuje poll() Najčastejšia chyba je robiť ťažkú prácu na poll threade.

Ak v incidente nevidíte kód, dá sa to vyčítať:

  • veľký processing time per batch
  • oneskorené commity
  • logy o prekročení max.poll

B. Či je skutočný bottleneck downstream (DB) U nás to bol DB pool.

Ak máte:

  • metriky poolu
  • DB latenciu
  • CPU nie je vysoké, ale throughput je nízky

Bezpečné mitigácie (poradie)

  1. Prestaňte zväčšovať group Nescaleujte ďalej, kým nie je STABLE.

  2. Znížiť prácu per poll

  • znížiť max.poll.records
  • presunúť spracovanie do worker poolu (poll thread nech stále polluje)
  • backpressure: nepoluj, ak je interná práca queue plná
  1. Zvýšiť max.poll.interval.ms (opatrne) Dá to čas pomalému spracovaniu bez vyhodenia z group.

  2. Cooperative rebalancing + static membership Zníži stop-the-world rebalancy pri deployoch a flappingu.

Rizikové mitigácie

  • extrémne veľké timeouty → pomalý failover pri reálnom páde
  • rozbitá disciplína commitov → duplicity a data loss
  • agresívne retries bez idempotencie

Čo sme zmenili (konkrétne config diffs)

Predtým (príliš optimistické):

enable.auto.commit=true
max.poll.records=500
max.poll.interval.ms=300000
session.timeout.ms=10000
heartbeat.interval.ms=3000
partition.assignment.strategy=org.apache.kafka.clients.consumer.RangeAssignor

Potom (stabilnejšie, deploy-friendly):

enable.auto.commit=false
max.poll.records=50
max.poll.interval.ms=1800000
session.timeout.ms=30000
heartbeat.interval.ms=10000
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
group.instance.id=${HOSTNAME}

V kóde sme zabezpečili:

  • poll thread iba polluje a enqueueuje prácu
  • worker pool spracuje recordy
  • offset commit až po úspešnom spracovaní
  • idempotentné správanie (alebo idempotency keys)

Ako verifikovať

  1. Group ostane STABLE Spustite --describe --members viackrát počas 10–15 min. Membership nesmie flappovať.

  2. Rebalance frekvencia padne V logoch majú byť revokácie zriedkavé (typicky iba počas deploy okna).

  3. Lag klesá monotónne Po stabilizácii má lag trendovať dole. Ak osciluje, stále máte nestabilitu.

  4. Downstream tlak sa zlepší DB pool prestane thrashovať, latencie sa stabilizujú.

Prevencia / guardrails

  • Rebalance budget
    • alert ak rebalancy prekročia N/hod
  • Poll-time budget
    • maximálny čas spracovania na poll cyklus
  • Idempotency kontrakt
    • duplicity sa v niektorých failure modoch dejú; spravte ich safe
  • Backpressure kontrakt
    • consumer musí prestať polovať, keď je downstream saturovaný

Súvisiace čítanie

Súvisiace články

Citujte tento článok

Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.

Michal Drozd. "Kafka rebalance búrky: prečo scale-out consumerov vie zhoršiť lag". https://www.michal-drozd.com/sk/blog/kafka-consumer-rebalance-burka/ (Publikované 10. novembra 2025).