提出问题
下图,主题中有 3 个分区,消费者组中有 3 个消费者,哪个消费者消费哪个分区的消息?
这就涉及到 Kafka 消费者的 分区分配策略
分区分配策略
一个 consumer group 中有多个 consumer,一个 topic 有多个 partition
有两种策略,决定哪个 partition 由哪个 consumer 来消费:
- Range,范围分区,默认使用
- RoundRobin,轮询分区
- sticky
Range
让 所有 consumer 平均消费 partition
默认策略
对同一个topic中的 partition 按照序号排序,并对 consumer 按照字典顺序排序
为每个consumer划分固定的分区范围,如果不够平均分配,那么排序靠前的 consumer 会 多分配分区
如下图:因为 10除3除不尽,所以 consumer0 会多分配一个分区
缺点
如上,只是针对 1 个 topic 而言,消费者 consumer0 多消费1个分区影响不是很大。
如果有 N 多个 topic,那么针对每个 topic,消费者 consumer0 都将多消费 1 个分区,topic越多,consumer0 消费的分区会比其他消费者 多消费 N 个分区。
这就是 Range 范围分区的一个很明显的弊端了
解决:可通过 RoundRobin 轮询分区策略
RoundRobin
将消费组内所有消费者,消费者订阅的所有主题的分区按照字典序排序,然后通过轮询方式逐个将分区依次分配给每个消费者。
情况一
同一个消费组内,所有的消费者的订阅信息都是 相同 的,那么分区分配是 均匀 的
例子
消费组中有2个消费者,都订阅了主题 t0 和 t1,并且每个主题都有 3 个分区
订阅的所有分区可以标识为:t0p0、t0p1、t0p2、t1p0、t1p1、t1p2
分配结果如下图:
消费者C0:t0p0、t0p2、t1p1
消费者C1:t0p1、t1p0、t1p2
情况二
同一个消费组内,所有的消费者的订阅信息 不相同,那么在执行分区分配的时候就不是完全的轮询分配,有可能导致分区分配得 不均匀
例子
同一消费者组中,有3个消费者 C0、C1 和 C2,他们共订阅了 3 个主题:
- t0,有1个分区(p0)
- t1,有2个分区(p0、p1)
- t2,有3个分区(p0、p1、p2))
分区情况如下图:
消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2
缺点
从情况二可以看到 RoundRobinAssignor 策略也不是十分完美,这样分配其实并不是最优解
类
org.apache.kafka.clients.consumer.RoundRobinAssignor
Sticky
sticky 这个单词可以翻译为“黏性的”,Kafka 从 0.11.x 版本开始引入这种分配策略
目标:
- 分区的分配要尽可能均匀
- 分区的分配尽可能与上次分配的保持相同
当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor 分配策略的具体实现要复杂得多。
情况一:订阅信息相同
例子
消费组内有3个消费者(C0、C1 和 C2),它们都订阅了4个主题(t0、t1、t2、t3),并且每个主题有2个分区。也就是说,整个消费组订阅了 t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1 这8个分区。
分配结果如下图:
消费者C0:t0p0、t1p1、t3p0
消费者C1:t0p1、t2p0、t3p1
消费者C2:t1p0、t2p1
看上去似乎与采用 RoundRobinAssignor 分配策略所分配的结果相同
例子2
假设此时消费者 C1 脱离了消费组,那么消费组就会执行再均衡操作,进而消费分区会重新分配。
分配结果如下图:
消费者C0:t0p0、t1p1、t3p0、t2p0
消费者C2:t1p0、t2p1、t0p1、t3p1
可以看到分配结果中 保留了上一次分配 中对消费者 C0 和 C2 的所有分配结果,并将原来消费者 C1 的分区分配给了剩余的两个消费者 C0 和 C2,最终 C0 和 C2 的分配还保持了均衡。
情况二:订阅信息不同
同样消费组内有3个消费者(C0、C1 和 C2),集群中有3个主题(t0、t1 和 t2),这3个主题分别有1、2、3个分区。
也就是说,集群中有 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 这6个分区。消费者 C0 订阅了主题 t0,消费者 C1 订阅了主题 t0 和 t1,消费者 C2 订阅了主题 t0、t1 和 t2
分配结果如下图:
消费者C0:t0p0
消费者C1:t1p0、t1p1
消费者C2:t2p0、t2p1、t2p2
可以看到这才是一个最优解(消费者 C0 没有订阅主题 t1 和 t2,所以不能分配主题 t1 和 t2 中的任何分区给它,对于消费者 C1 也可同理推断)
参考:
https://blog.csdn.net/qq_21383435/article/details/108720155
https://cloud.tencent.com/developer/article/1791969






