Kafka详解(八)消费者组重平衡全流程

消费者组的重平衡流程,它的作用是让组内所有的消费者实例就消费哪些主题分区达成一致。重平衡需要借助 Kafka Broker 端的 Coordinator 组件,在 Coordinator 的帮助下完成整个消费者组的分区重分配。今天我们就来详细说说这个流程。

1. 触发条件

消费者组重平衡触发的3个条件:

  1. 组成员数量发生变化
  2. 订阅主题数量发生变化
  3. 订阅主题的分区数发生变化

在实际生产环境中,因条件1而引发的重平衡是最常见的(消费者组中的消费者实例依次启动也属于第1种情况,每次消费者组启动,必定触发重平衡)。

2. 通知方式

Kafka消费者需要定期发送心跳请求(Heartbeat Request)到Broker端的协调者。从0.10.1.0版本开始,Kafka引入了专门发送心跳请求的线程(Heartbeat Thread)。重平衡的通知机制正是通过心跳线程来完成的。当协调者决定开启新一轮重平衡时,会将“REBALANCE_IN_PROCESS”封装进心跳请求的响应中,发还给消费者实例。

因此heartbeat.interval.ms参数除了设置心跳的时间间隔,也同时决定了重平衡通知的频率。如果想要消费者快速得到通知,那么可以将这个参数设置为非常小的值,这样消费者就可以更快的收到重平衡的响应消息。

3. 消费者组状态机

Kafka设计了一套消费者组状态机(State Machine),共有五种状态:Empty、Dead、PreparingRebalance、CompletingRebalance和Stable。

了解了这些状态的含义之后,我们来看一张图片,它展示了状态机的各个状态流转。

上图表明了消费者组启动时的状态流转过程。一个消费者组最开始是 Empty 状态,当重平衡过程开启后,它会被置于 PreparingRebalance 状态等待成员加入,之后变更到 CompletingRebalance 状态等待分配方案,最后流转到 Stable 状态完成重平衡。

4. 消费者端重平衡流程

在消费者端,重平衡分为两个步骤:分别是加入组和等待领导者消费者(Leader Consumer)分配方案。这两个步骤分别对应两类特定的请求:JoinGroup 请求SyncGroup 请求

4.1 JoinGroup请求

当组内成员加入组时,它会向协调者发送 JoinGroup 请求。在该请求中,每个成员都要将自己订阅的主题上报,这样协调者就能收集到所有成员的订阅信息。一旦收集了全部成员的 JoinGroup 请求后,协调者会从这些成员中选择一个担任这个消费者组的领导者。

通常情况下,第一个发送 JoinGroup 请求的成员自动成为领导者。要注意区分这里的领导者和之前我们介绍的领导者副本,它们不是一个概念。这里的领导者是具体的消费者实例,它既不是副本,也不是协调者。领导者消费者的任务是收集所有成员的订阅信息,然后根据这些信息,制定具体的分区消费分配方案。

选出领导者之后,协调者会把消费者组订阅信息封装进 JoinGroup 请求的响应体中,然后发给领导者,由领导者统一做出分配方案后,进入到下一步:发送 SyncGroup 请求。如下图所示:

4.2 SyncGroup请求

在这一步中,领导者向协调者发送 SyncGroup 请求,将刚刚做出的分配方案发给协调者。值得注意的是,其他成员也会向协调者发送 SyncGroup 请求,只不过请求体中并没有实际的内容。这一步的主要目的是让协调者接收分配方案,然后统一以 SyncGroup 响应的方式分发给所有成员,这样组内所有成员就都知道自己该消费哪些分区了。

SyncGroup 请求的主要目的,就是让协调者把领导者制定的分配方案下发给各个组内成员。当所有成员都成功接收到分配方案后,消费者组进入到 Stable 状态,即开始正常的消费工作。

如下图所示:

5. Broker端(协调者Coordinator)重平衡流程

要分析协调者处理重平衡的全流程,需要分以下几个场景来讨论。

5.1 新成员加入场景

新成员入组是指组处于 Stable 状态后,有新成员加入。

当协调者收到新的 JoinGroup 请求后,它会通过心跳请求响应的方式通知组内现有的所有成员,强制它们开启新一轮的重平衡。具体的过程和之前的客户端重平衡流程是一样的。如下图所示:

5.2 组成员主动离组场景

主动离组,就是指消费者实例所在线程或进程调用 close() 方法主动通知协调者它要退出。这个场景就涉及到了第三类请求:LeaveGroup 请求。协调者收到 LeaveGroup 请求后,依然会以心跳响应的方式通知其他成员。如下图所示:

5.3 组成员崩溃离组场景

崩溃离组是指消费者实例出现严重故障,突然宕机导致的离组。它和主动离组是有区别的,因为后者是主动发起的离组,协调者能马上感知并处理。但崩溃离组是被动的,协调者通常需要等待一段时间才能感知到,这段时间一般是由消费者端参数 session.timeout.ms 控制的。也就是说,Kafka 一般不会超过 session.timeout.ms 就能感知到这个崩溃。当然,后面处理崩溃离组的流程与之前是一样的。如下图所示:

5.4 重平衡时协调者对组内成员提交位移的处理

正常情况下,每个组内成员都会定期汇报位移给协调者。当重平衡开启时,协调者会给予成员一段缓冲时间,要求每个成员必须在这段时间内快速地上报自己的位移信息,然后再开启正常的 JoinGroup/SyncGroup 请求发送。

发布了8 篇原创文章 · 获赞 0 · 访问量 7277

猜你喜欢

转载自blog.csdn.net/fedorafrog/article/details/104099674