Kafka的rebalance机制

1、什么是 rebalance 机制

重平衡(rebalance)机制规定了如何让消费者组下的所有消费者来分配 topic 中的每一个分区。

2、rebalance 机制的触发条件是什么
(1)消费者组内成员变更
成员增加 :当有新的消费者加入到消费者组时,会触发重平衡以重新分配分区。
成员减少

主动离组:某个消费者调用 close() 方法显式退出消费者组。

被动离组:由于网络故障、应用程序崩溃或其他原因导致消费者无法发送心跳请求给协调者(Coordinator),超过一定时间(session.timeout.msmax.poll.interval.ms),协调者认为该消费者已死亡并将其移除。
(2)订阅 topic 的数量发生变化

如果消费者组使用正则表达式订阅了多个 topic,并且新增了一个符合该模式的新 topic,这将触发 rebalance 以便新主题的分区可以被分配给现有消费者。
(3)订阅 topic 的分区数发生变化

当某个 topic 的分区数增加时(Kafka 支持动态增加分区),为了使新增加的分区能够被合理分配,也会触发 rebalance。

3、rebalance 机制的影响是什么
(1)消费中断
消息消费暂停 :rebalance 过程中,所有消费者都会暂时停止,直到新的分配方案确定并生效。
(2)资源消耗增加
网络流量增加 :rebalance 期间,消费者需要重新建立与协调者(Coordinator)的连接,并接收新的分区分配信息。这会生成额外的网络流量。
CPU 和内存使用上升 :频繁的 rebalance 会导致更多的 CPU 和内存用于处理心跳请求、位移提交以及重新分配逻辑,增加了 Broker 和消费者负载。
(3)延迟增大

由于消息消费暂停,已经到达但尚未处理的消息会被延迟处理,可能导致端到端的延迟增加。

4、如何减少 rebalance 的发生

rebalance 的触发条件中,2 和 3 可以人为约定规范的方式来减少 rebalance,但往往第一种情况才是引起 rebalance 的最常见原因

除了消费者成员正常的添加和停止之外,还有些情况下 Coordinator 会错误的认为消费者组成员已停止而将其踢出组以致发生 rebalance。

我们知道维持分布式系统的方式通常是通过发送心跳的,kafka也不例外。

由于一些问题,你可能不清楚没接收到心跳的原因,比如是因为对方真正挂了还是只因为当时负载过高或网络堵塞没来得及发心跳等。所以一般会约定一个时间,超时即判定对方挂了。而在 kafka 消费场景中,session.timout.ms 参数就是规定这个超时时间的。

另外一个参数是 heartbeat.interval.ms,它控制发送心跳的频率,频率越高越不容易被误判,当然代价是会消耗更多资源。

此外,还有一个参数,max.poll.interval.ms,我们知道消费者 poll 数据后,需要进行处理然后再拉取。但如果两次拉取时间间隔超过这个参数的值,那消费者就会被踢出消费者组。也就是说处理时间不能超过 max.poll.interval.ms。该参数的默认值是 5 分钟,如果消费者接收到数据后会执行耗时操作,则应将其设置得大些。

总结一下几个参数

通过上述可知,一般建议如下

(1)heartbeat.interval.ms < session.timeout.ms:确保心跳间隔足够短,以便及时发现消费者故障,但又不会过于频繁发送心跳请求,增加网络开销。

(2)max.poll.interval.ms > 处理时间:确保这个值大于消费者处理消息所需最大时间,以避免由于处理时间过长而被误认为死亡。

5、rebalance 的三种策略
(1)Range

基于每个主题的分区分配,先对同一个 topic 里面的分区按照序号排序,并对消费者按照字母序进行排序。假如一个 topic下有 10 个分区,3 个消费者,排序后的分区是 0,1,2,3,4,5,6,7,8,9,消费者排序完之后将会是C1, C2, C3。通过 partition数/consumer数 来决定每个消费者应该消费几个分区。如果除不尽,那么前面消费者将会多消费 1 个分区。

例如,10/3 = 3 余 1 ,除不尽,那么 消费者 C1 便会多消费 1 个分区,最终分配结果如下:

C1 0,1,2,3 分区

C2 4,5,6 分区

C3 7,8,9 分区(如果有11 个分区的话,C1 将消费 0,1,2,3 分区,C2 将消费4,5,6,7 分区 C3 将消费 8,9,10 分区)

Range 的弊端:

如上,只是针对 1 个 topic 而言,C1 消费者多消费 1 个分区影响不是很大。如果有 N 个 topic,那么针对每个 topic,消费者 C1 都将多消费 1 个分区,topic 越多,C1 消费的分区会比其他消费者明显多 N 个分区。

(2)RoundRobin(默认策略)

轮询分区,kafka 默认的 rebalance 策略,把所有的 partition 和 consumer 都列出来,通过轮询来分配 partition 到消费者。

轮询分区分为如下两种情况:

①同一消费组内所有消费者订阅的 topic 都是相同的

②同一消费者组内的消费者订阅的 topic 不同

对于第一种情况,RoundRobin 策略的分区分配是均匀的。

例如:同一消费者组中,有 3 个消费者 C0、C1 和 C2,都订阅了 2 个主题 t0 和 t1,并且每个主题都有 3 个分区(p0、p1、p2),那么所订阅的所以分区可以标识为t0p0、t0p1、t0p2、t1p0、t1p1、t1p2。最终分区分配结果如下:

消费者C0 消费 t0p0 、t1p0 分区

消费者C1 消费 t0p1 、t1p1 分区

消费者C2 消费 t0p2 、t1p2 分区

对于第二种情况,可能会导致分区分配不均匀。如果某个消费者没有订阅消费组内的某个 topic,那么在分配分区的时候,此消费者将不会分配到这个 topic 的任何分区。

例如:同一消费者组中,有 3 个消费者 C0、C1 和 C2,他们共订阅了 3 个主题:t0、t1 和 t2,这 3 个主题分别有 1、2、3 个分区(即:t0有1个分区(p0),t1有 2 个分区(p0、p1),t2 有 3 个分区(p0、p1、p2)),即整个消费者所订阅的所有分区可以标识为 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2。具体而言,消费者 C0 订阅的是主题 t0,消费者 C1 订阅的是主题 t0 和 t1,消费者 C2 订阅的是主题 t0、t1 和t2,最终分区分配结果如下:

消费者C0 消费 t0p0

消费者C1 消费 t1p0 分区

消费者C2 消费 t1p1、t2p0、t2p1、t2p2 分区

(3)Sticky

粘性分配策略,主要是为了让目前的分配尽可能保持不变,只挪动尽可能少的分区来实现重平衡。

举例,有三个消费者 C0,C1,C2 。三个主题 t0,t1,t2,t3。每个主题各有两个分区, t0p0,t0p1,t1p0,t1p1,t2p0,t2p1,t3p0,t3p1。

现在订阅情况如下:

C0:t0p0,t1p1,t3p0

C1:t0p1,t2p0,t3p1

C2:t1p0,t2p1

假设现在 C1 挂掉了,如果是 RoundRobin 分配策略,那么会变成下面这样:

C0:t0p0,t1p0,t2p0,t3p0

C2:t0p1,t1p1,t2p1,t3p1

就是说它会全部重新打乱,再分配,而如果使用 Sticky 分配策略,会变成这样:

C0:t0p0,t1p1,t3p0,t2p0

C2:t1p0,t2p1,t0p1,t3p1

也就是说,尽可能保留了原来的分区情况,不去改变它,在这个基础上进行均衡分配。

大佬,点个赞在走呗!

相关推荐
数据智能老司机7 小时前
CockroachDB权威指南——CockroachDB SQL
数据库·分布式·架构
数据智能老司机7 小时前
CockroachDB权威指南——开始使用
数据库·分布式·架构
数据智能老司机8 小时前
CockroachDB权威指南——CockroachDB 架构
数据库·分布式·架构
IT成长日记8 小时前
【Kafka基础】Kafka工作原理解析
分布式·kafka
州周10 小时前
kafka副本同步时HW和LEO
分布式·kafka
ChinaRainbowSea11 小时前
1. 初始 RabbitMQ 消息队列
java·中间件·rabbitmq·java-rabbitmq
爱的叹息11 小时前
主流数据库的存储引擎/存储机制的详细对比分析,涵盖关系型数据库、NoSQL数据库和分布式数据库
数据库·分布式·nosql
程序媛学姐11 小时前
SpringKafka错误处理:重试机制与死信队列
java·开发语言·spring·kafka
千层冷面12 小时前
RabbitMQ 发送者确认机制详解
分布式·rabbitmq·ruby
ChinaRainbowSea12 小时前
3. RabbitMQ 的(Hello World) 和 RabbitMQ 的(Work Queues)工作队列
java·分布式·后端·rabbitmq·ruby·java-rabbitmq