消费者重新平衡决定哪个消费者负责某些主题的所有可用分区的哪个子集。例如,您可能有一个具有 20 个分区和 10 个消费者的主题;在重新平衡结束时,您可能希望每个消费者从 2 个分区中读取数据。如果您关闭其中的 10 个消费者,您可能希望每个消费者在重新平衡完成后拥有 1 个分区。消费者重新平衡是一种动态分区分配,可以由 Kafka 自动处理。
Group Coordinator是负责与消费者通信以实现消费者之间重新平衡的代理之一。在早期版本中,Zookeeper 存储元数据详细信息,但最新版本存储在代理上。消费者协调器接收来自消费者组的所有消费者的心跳和轮询,因此请注意每个消费者的心跳并管理他们在分区上的偏移量。
组长:
一个消费者组作为组长,由组协调员选择,负责代表组中的所有消费者做出分区分配决策。
再平衡场景:
消费者组订阅任何主题
消费者实例无法发送带有 session.heart.beat 时间间隔的心跳。
消费者长进程超过轮询超时
消费者组的消费者通过异常
添加了新分区。
扩大和缩小消费者。手动添加新消费者或删除现有消费者
消费者再平衡
当消费者请求加入或离开群组时发起消费者重新平衡。Group Leader 从 Group Coordinator 收到所有活跃消费者的列表。Group Leader 使用 PartitionAssigner 决定分配给每个消费者的分区。一旦 Group Leader 完成分区分配,它会将分配列表发送给 Group Coordinator,Group Coordinator 会将这些信息发回给所有消费者。组仅将适用的分区发送给他们的消费者,而不是其他消费者分配的分区。只有 Group Leader 知道所有消费者及其分配的分区。重新平衡完成后,消费者开始向 Group Coordinator 发送 Heartbeat,表明它还活着。消费者向 Group Coordinator 发送一个 OffsetFetch 请求,以获取其分配的分区的最后提交的偏移量。
状态管理
在重新平衡时,Group coordinator 将其状态设置为 Rebalance 并等待所有消费者重新加入该组。
当组开始重新平衡时,组协调器首先将其状态切换为重新平衡,以便通知所有交互的消费者重新加入组。一旦重新平衡完成,组协调器创建新的生成 ID 并通知所有消费者和组继续同步阶段,消费者发送同步请求并继续等待组领导完成生成新的分配分区。一旦消费者收到一个新的分配分区,他们就会进入一个稳定的阶段。

静态成员
这种重新平衡是一项相当繁重的操作,因为它需要停止所有消费者并等待获取新分配的分区。在每次重新平衡时,总是创建新的一代 id 意味着刷新一切。为了解决这个开销,Kafka 2.3+ 引入了静态成员来减少不必要的重新平衡。KIP-345
在静态成员中,消费者状态将持续存在,并且在重新平衡时,相同的分配将得到应用。它使用新的 group.instance.id 来保留成员身份。因此,即使在最坏的情况下,成员 id 也会重新洗牌以分配新分区,但相同的消费者实例 ID 仍将获得相同的分区分配
instanceId: A, memberId: 1, assignment: {0, 1, 2}
instanceId: B, memberId: 2, assignment: {3, 4, 5}
instanceId: C, memberId: 3, assignment: {6, 7, 8}
重启后:
instanceId: A, memberId: 4, assignment: {0, 1, 2}
instanceId: B, memberId: 2, assignment: {3, 4, 5}
instanceId: C, memberId: 3, assignment: {6, 7, 8}
参考:
https://www.confluent.io/blog/kafka-rebalance-protocol-static-membership
https://cwiki.apache.org/confluence/display/KAFKA/KIP-345%3A+Introduce+static+membership+protocol+to+reduce+consumer+rebalances