Kafka 3.x 新的增量重平衡机制解析(实用篇)

63 阅读4分钟

下面给你详细讲解 Kafka 3.x 的 Incremental Cooperative Rebalancing(增量协作式重平衡) ,这是 Kafka 在高吞吐实时系统中非常重要的优化之一,能显著减少停顿时间和抖动。

内容会分 5 部分讲:

  1. 它解决了什么问题
  2. 与旧的 Rebalance 方式对比
  3. 增量重平衡的核心机制
  4. 实际案例演示(非常重要)
  5. 如何启用以及注意点

1. 传统 Rebalance 的痛点是什么?(为什么要改它?)

Kafka 2.x 以前默认是

EAGER

(急切式) rebalance:

重平衡触发时:

  • 所有消费者 必须先全部放弃分区
  • 再统一重新分配分区

导致问题:

问题影响
消费完全中断(全停顿)业务延迟激增
频繁 rebalance 时系统抖动严重稳定性下降
大组规模下 rebalance 时间更长甚至会雪崩

这种停顿往往持续 数秒甚至十几秒

特别是如果某个消费者执行较慢 poll/commit 操作,整个 group 就一直处于阻塞状态。

Kafka 在高吞吐业务(订单、日志流、计费、推荐系统等)中尤其容易遇到这个问题。


2. Kafka 3.x 的新增机制:Incremental Cooperative Rebalancing

Kafka 新版本提供了 合作式(Cooperative) rebalance,它的核心理念是:

让消费者只撤销必要的分区,而不需要全集体暂停,从而做到“边 rebalance 边消费”。

也叫:

  • Incremental Rebalance
  • Cooperative Rebalance
  • 增量重平衡

默认的 partition assignor 为:

  • CooperativeStickyAssignor

3. 增量重平衡的核心机制(重点)

增量重平衡的本质:

⚙️ 原理核心

在 rebalance 过程中:

  • 消费者不再一次性丢弃所有分区
  • 而是执行 两阶段重平衡

阶段 1:撤销部分分区(Partial Revoke)

消费者收到 rebalance 开始的通知时:

  • 只释放那些不再属于自己的分区
  • 保留仍可以继续消费的分区,不会停顿

这意味着消费仍然可以在过程中继续推进。


阶段 2:分配新分区(Assign New Partitions)

在所有消费者释放完必要的分区后:

  • 再进行一次轻量级 rebalance
  • 将“被释放的分区”重新分配

因为此时:

  • 未必所有消费者都会撤销分区
  • 分配集很小
  • 因此重平衡影响范围显著缩小

最终效果:

大部分情况下,只有非常少量的分区被迁移,消费者不会完全停顿。


4. 实际案例演示(非常重要,能让你一下理解)

假设:

  • Topic 有 6 个分区
  • Consumer Group 有 3 个消费者:C1, C2, C3

初始分配:

  • C1 → p0, p1
  • C2 → p2, p3
  • C3 → p4, p5

🆕

现在新加入 C4

✔️ 旧的 EAGER Rebalance:

  1. 所有消费者全部放弃(撤销 p0~p5)

  2. 整个组进入停顿状态

  3. 重新分配 6 个分区给 4 个消费者

  4. 全组恢复消费

    停顿较长,很痛苦


✔️ Incremental Cooperative Rebalance:两次小操作即可

🟦第一次:局部释放

新方案下,第一次分配时,会要求:

  • C1、C2、C3 只释放部分分区

可能仅释放:

  • C1:p1
  • C2:p3
  • C3:p5

这些分区“让出来”给 C4。

但关键点:

  • C1、C2、C3 还继续消费剩下的 p0、p2、p4(不暂停)
  • C4 暂时什么分区都没有(等第二次)

🟧第二次:最终分配

在第二阶段,Kafka 将被释放的 p1、p3、p5 分配给 C4,完成整个 rebalance。

最终效果:

  • 没有全局停顿
  • 只有必要分区被迁移
  • rebalance 影响范围变得很小

5. 如何启用增量重平衡(非常简单)

消费者客户端配置:

partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor

或新版写法:

partition.assignment.strategy=cooperative-sticky

消费者代码(Java):

props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    Collections.singletonList(CooperativeStickyAssignor.class.getName()));

6. 注意事项

⭐ 必须让所有 consumer 都使用 CooperativeStickyAssignor

否则会导致不可预期的 rebalance 行为。


⭐ 重写 onPartitionsAssigned 与 onPartitionsRevoked

增量模式下:

  • revoked 的分区是不完整的(只部分)
  • assigned 的分区也可能是增量的

→ 必须支持“增量处理”,不能假设是全量更新。


⭐ 提升大消费者组的稳定性

如果 group 有几十上百个消费者,效果非常显著。


🏁总结一句话

Kafka 3.x 的增量重平衡让消费者在 rebalance 时不再全体停顿,只撤销必要的分区,大幅降低业务延迟和系统抖动,是企业生产环境强烈推荐启用的模式。