← 中文资源

简体中文版本

Kafka 重平衡风暴 — 消费组反复 Rebalance 的原因

通过协调器日志与消费组 generation 变化定位 Kafka 重平衡风暴,调整 max.poll.interval.ms、批大小与静态成员配置恢复稳定消费。

阅读英文原文

现象

消费端日志反复出现 Rebalance began 与 Revoking previously assigned partitions;每隔几分钟吞吐归零再恢复;日志里的 generation 不断增大;每次重平衡后部分消息被重复处理。

诊断

连续两次查看消费组状态,间隔约一分钟:

kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --describe --group orders --state --members --verbose

若 generation 持续变化、分区归属在没有发布的情况下漂移,或状态长期停在 PreparingRebalance,即可确认存在循环。随后在消费端日志中查原因:

kubectl logs deploy/orders-consumer --since=30m | \
  grep -E 'Rebalance|max.poll.interval|poll timeout|LeaveGroup' | tail -50

出现 consumer poll timeout has expired 说明单批处理时间超过 max.poll.interval.ms;若是心跳失败,则要排查 GC 停顿、网络抖动或 session.timeout.ms 过小。最后用 --describe --under-replicated-partitions 和 broker 日志排除副本切换导致的成员抖动。

修复

降低 max.poll.records,让最慢一批也能在轮询间隔内处理完;确实单条耗时较长时,提高 max.poll.interval.ms 并把握手与处理线程分离。为消费者设置 group.instance.id 启用静态成员,滚动发布时不会触发全组重平衡;使用 CooperativeStickyAssignor 只撤销必须迁移的分区。示例配置:

max.poll.records=100
max.poll.interval.ms=600000
session.timeout.ms=60000
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
group.instance.id=orders-pod-3

验证

持续观察至少三个原本会触发重平衡的窗口:generation 应保持不变,状态稳定为 Stable,lag 单调下降,日志中不再出现 poll timeout。再用静态成员做一次 Pod 重启,确认成员能在会话超时内重新加入且不全量撤销分区。最后核对下游幂等指标,确保这次风暴没有留下重复副作用。