kafka消费者组与重平衡机制有了解吗?
(虾皮一面)
传统消息队列有两种方式:队列和发布订阅。
kafka借助kafka的消费者组机制,可以同时实现这两种模型
1、消费者组的概念
- 消费者组由多个消费者组成,共享一个group id。
- 一个消费者组中,每个分区只能由组内的一个消费者订阅
- 当消费者组中只有一个消费者的时候,就是消息队列模型,不然就是发布-订阅模型,并且易于伸缩
- 一般让消费者组内消费者小于或等于分区数,以及topic分区数是消费者组内成员数的倍数。
否则会让消费者组里面的某些节点空闲
2、重平衡(Rebalance)
规定了如何让消费者组下的所有消费者来分配topic中的每一个分区
2.1、触发条件:
- 消费者组内发生变化(增加或者减少了消费者,或者网络崩溃退出)
- 主题中的分区数变化,
- 订阅的主题发生变化
2.2、重平衡的方式
- Range: (范围分区,默认)消费者被分配的单位是基于主题的 ,如果主题的分区不能平均分配给组内每个消费者,那么对该主题,某些消费者会被分配到额外的分区。我们来看看具体的例子
- RoundRobin:(轮询) 是基于全部主题的分区来进行分配的, 这种分配策略能更加均衡得分配分区给每一个消费者
同一组内的消费者订阅不同的主题,那么任然可能会导致分区不均衡的情况 - Sticky: 目前的分配尽可能保持不变,只挪动尽可能少的分区来实现重平衡。
2.3重平衡的影响
重平衡过程中,消费者无法从kafka消费消息,而如果kafka集内节点较多,比如数百个,那重平衡可能会耗时极多。而这段时间kafka基本处于不可用状态。所以在生产环境中,应该尽量避免重平衡发生。
2.4避免重平衡
- 减少kafka的分区分配,尽量在首次就确定好
- 完全避免重平衡是很难的,我们无法完全保证消费者不会故障。一个方式是减少网络误判
- session.timout.ms: 消费者与broker的心跳超时时间,默认10s,broker在指定时间内没有收到心跳请求,broker端将会将该消费者移出,并触发重平衡。
- heartbeat.interval.ms: 心跳间隔时间,消费者会以该频率向broker发送心跳,默认为3s,主要是确保session不会失效。 ( 心跳频率,频率越高越不容易被误判,但也会消耗更多资源 )
- max.poll.interval.ms: 两次poll方法调用的最大间隔时间,单位毫秒,默认为5分钟。如果消费端在该间隔内没有发起poll操作,该消费者将被剔除,触发重平衡,将该消费者分配的队列分配给其他消费者。
( 推荐为消费者处理消息最长耗时再加1分钟 )
总结:
kafka消费者组由多个消费者节点组成,用group id进行标识。 消费者组订阅的主题分区只能由某个消费者进行消费。所以一般都会让主题分区数大于且是消费者节点的倍数,否则会造成某些节点空闲或者消费分配不均。
消费者和分区的映射关系有三个方式:Range、RoundRobin、Sticky
当消费者数发生变化、主题分区数修改和订阅主题发生变化时,会触发重平衡
这时候会造成消费者无法消费。如果集群里节点较多,可能导致较长时间的不可用
所以要尽量避免重平衡,尽量减少生产环境的分区分配策略。另外因为网络故障导致消费者节点下线也是触发重平衡的原因,可以将一些超时判断配置适当的调大一些。