一、多重分区分配算法:RoundRobinAssignor
### --- RoundRobinAssignor
~~~ RoundRobinAssignor的分配策略是将消费组内订阅的所有Topic的分区
~~~ 及所有消费者进行排序后尽量均衡的分配(RangeAssignor是针对单个Topic的分区进行排序分配的)。
~~~ 如果消费组内,消费者订阅的Topic列表是相同的(每个消费者都订阅了相同的Topic),
~~~ 那么分配结果是尽量均衡的(消费者之间分配到的分区数的差值不会超过1)。
~~~ 如果订阅的Topic列表是不同的,那么分配结果是不保证“尽量均衡”的,
~~~ 因为某些消费者不参与一些Topic的分配。
### --- 相对于RangeAssignor,
~~~ 在订阅多个Topic的情况下,RoundRobinAssignor的方式能消费者之间尽量均衡的分配到分区
~~~ (分配到的分区数的差值不会超过1——RangeAssignor的分配策略可能随着订阅的Topic越来越多,
~~~ 差值越来越大)。
### --- 对于消费组内消费者订阅Topic不一致的情况:
~~~ 假设有两个个消费者分别为C0和C1,有2个TopicT1、T2,
~~~ 分别拥有3和2个分区,并且C0订阅T1和T2,C1订阅T2,那么RoundRobinAssignor的分配结果如下:
~~~ 看上去分配已经尽量的保证均衡了,不过可以发现C0承担了4个分区的消费而C1订阅了T2一个分区,
~~~ 是不是把T2P0交给C1消费能更加的均衡呢?
二、多重分区分配算法:StickyAssignor
### --- StickyAssignor
~~~ # 动机
~~~ 尽管RoundRobinAssignor已经在RangeAssignor上做了一些优化来更均衡的分配分区,
~~~ 但是在一些情况下依旧会产生严重的分配偏差,比如消费组中订阅的Topic列表不相同的情况下。
~~~ 更核心的问题是无论是RangeAssignor,还是RoundRobinAssignor,
~~~ 当前的分区分配算法都没有考虑上一次的分配结果。
~~~ 显然,在执行一次新的分配之前,如果能考虑到上一次分配的结果,
~~~ 尽量少的调整分区分配的变动,显然是能节省很多开销的。
~~~ # 目标
~~~ 从字面意义上看,Sticky是“粘性的”,可以理解为分配结果是带“粘性的”:
~~~ 1. 分区的分配尽量的均衡
~~~ 2. 每一次重分配的结果尽量与上一次分配结果保持一致
~~~ 当这两个目标发生冲突时,优先保证第一个目标。
~~~ 第一个目标是每个分配算法都尽量尝试去完成的,而第二个目标才真正体现出StickyAssignor特性的。
~~~ 我们先来看预期分配的结构,后续再具体分析StickyAssignor的算法实现。
### --- 例如:
~~~ 有3个Consumer:C0、C1、C2
~~~ 有4个Topic:T0、T1、T2、T3,每个Topic有2个分区
~~~ 所有Consumer都订阅了这4个分区
~~~ StickyAssignor的分配结果如下图所示(增加RoundRobinAssignor分配作为对比):
~~~ 如果消费者1宕机,则按照RoundRobin的方式分配结果如下:
~~~ 打乱从新来过,轮询分配:
~~~ 按照Sticky的方式:
~~~ 仅对消费者1分配的分区进行重分配,红线部分。最终达到均衡的目的。
### --- 再举一个例子:
~~~ 有3个Consumer:C0、C1、C2
~~~ 3个Topic:T0、T1、T2,它们分别有1、2、3个分区
~~~ C0订阅T0;C1订阅T0、T1;C2订阅T0、T1、T2
~~~ # 分配结果如下图所示:
~~~ 消费者0下线,则按照轮询的方式分配:
~~~ 按照Sticky方式分配分区,仅仅需要动的就是红线部分,其他部分不动。
~~~ StickyAssignor分配方式的实现稍微复杂点儿,我们可以先理解图示部分即可。感兴趣的同学可以研究一下。