避免消费者组非必要重平衡的方法
- 1、重平衡的 3 个弊端
- 1.1、影响 consumer 端 TPS
- 1.2、重平衡很慢
- 1.3、重平衡操作效率不高
- 2、非必要的 2 类 Rebalance
- 2.1、因为 Consumer 没能及时发送心跳请求,导致“被踢出” Group 而引发的。
- 2.2、非必要 Rebalance 是 Consumer 消费时间过长导致的。
重平衡就是让一个 Consumer Group 下所有的 Consumer 实例就如何消费订阅主题的所有分区达成共识的过程。
1、重平衡的 3 个弊端
1.1、影响 consumer 端 TPS
在 Rebalance 过程中,所有 Consumer 实例共同参与,在协调者组件的帮助下,完成订阅主题分区的分配。但是,在整个过程中,所有实例都不能消费任何消息,因此它对 Consumer 的 TPS 影响很大。
1.2、重平衡很慢
测试 Group 下有几百个 Consumer 实例,Rebalance 一次要几个小时。在那种场景下,Consumer Group 的 Rebalance 已经完全失控了。
1.3、重平衡操作效率不高
当前 Kafka 的设计机制决定了每次 Rebalance 时,Group 下的所有成员都要参与进来,而且通常不会考虑局部性原理,但局部性原理对提升系统性能是特别重要的。
举个例子。比如一个 Group 下有 10 个成员,每个成员平均消费 5 个分区。假设现在有一个成员退出了,此时就需要开启新一轮的 Rebalance,把这个成员之前负责的 5 个分区“转移”给其他成员。显然,比较好的做法是维持当前 9 个成员消费分区的方案不变,然后将 5 个分区随机分配给这 9 个成员,这样能最大限度地减少 Rebalance 对剩余 Consumer 成员的冲击。
但目前 Kafka 并不是这样设计的。在默认情况下,每次 Rebalance 时,之前的分配方案都不会被保留。就拿上面例子来说,当 Rebalance 开始时,Group 会打散这 50 个分区(10 个成员 * 5 个分区),由当前存活的 9 个成员重新分配它们。显然这不是效率很高的做法。
2、非必要的 2 类 Rebalance
要避免Rebalance,还是要从Rebalance发生的时机入手。我们在前面说过,Rebalance发生的时机有三个:
- 组成员数量发生变化
- 订阅主题数量发生变化
- 订阅主题的分区数发生变化
后面两个通常都是运维的主动操作,所以它们引发的 Rebalance 大都是不可避免的。接下来,我们主要说说因为组成员数量变化而引发的 Rebalance 该如何避免。
2.1、因为 Consumer 没能及时发送心跳请求,导致“被踢出” Group 而引发的。
session.timeout.ms,该参数的默认值是10秒,即如果Coordinator在10秒之内没有收到Group下某Consumer实例的心跳,它就会认为这个Consumer实例已经挂了。
heartbeat.interval.ms。这个值设置得越小,Consumer实例发送心跳请求的频率就越高。频繁地发送心跳请求会额外消耗带宽资源
建议配置如下:
- 设置session.timeout.ms = 6s。
- 设置heartbeat.interval.ms = 2s。
- 要保证Consumer实例在被判定为“dead”之前,能够发送至少3轮的心跳请求,即session.timeout.ms >= 3 * heartbeat.interval.ms。
2.2、非必要 Rebalance 是 Consumer 消费时间过长导致的。
- max.poll.interval.ms,该参数值是配置 Kafka 消费者常用超时时间,设置得大一点,比你的业务最大处理时间稍长一点。