分区在集群中的分配策略
- 将所有broker(n个)和partition排序
- 将第i个Partition分配到第(i mode n)个broker上
Producer 把消息发送给对应分区策略
- 当key和partition都为空时,消息随机发送到各个分区(各个版本会有不同,有的是采用轮询的方式,有的是随机,有的是一定时间内只发送给固定partition,隔一段时间后随机换一个)
- 当partition空,单key不为空时,用key的ha’sh值对partion个数取模,决定要把消息发送到哪个partition上
- 当key和partition都不为空时,只会根据partition发送到对应的partition上
- 当key为空、partition不为空时,根据partition发送到指定的partition上
消费者分区分配策略
1.RangePartitionAssignor(默认):
针对每一个topic:
n = 分区数/消费者数量
m = 分区数%消费者数量
前m个消费者每个分配n+1个分区,后面的 (消费者数量-m)个消费者每个分配n个分区
假如有10个分区,3个消费者,把分区按照序号排列0,1,2,3,4,5,6,7,8,9;消费者为C1,C2,C3,那么用分区数除以消费者数来决定每个Consumer消费几个Partition,除不尽的前面几个消费者将会多消费一个
最后分配结果如下
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
假如我们有两个主题T1,T2,分别有10个分区,最后的分配结果将会是这样:
C1:T1(0,1,2,3) T2(0,1,2,3)
C2:T1(4,5,6) T2(4,5,6)
C3:T1(7,8,9) T2(7,8,9)
在这种情况下,C1多消费了两个分区
2.RoundRobinAssignor:
将所有的Topic和Partition按照字典顺序排序,然后对每个Consumer进行轮询分配
roundrobin策略针对于全局所有的topic和消费者,分配步骤如下:
1. 消费者按照字典排序,例如C0, C1, C2… …,并构造环形迭代器。
2. topic名称按照字典排序,并得到每个topic的所有分区,从而得到所有分区集合。
3. 遍历第2步所有分区集合,同时轮询消费者。
4. 如果轮询到的消费者订阅的topic不包括当前遍历的分区所属topic,则跳过;否则分配给当前消费者,并继续第3步。
所以对于某个topic来说:
如果有5个分区(P0, P1, P2, P3, P4),且订阅这个topic的消费者组有2个消费者(C0, C1)。那么P0, P2, P4将被C0消费,P1, P3将被C1消费。
roundrobin策略如下图所示:
如图所示:
3个Topic:T0(3个分区0, 1, 2), T1(两个分区0, 1), T2(4个分区0, 1, 2, 3);
3个consumer: C0订阅了[T0, T1], C1订阅了[T1, T2], C2订阅了[T2, T0];
roundrobin结果分配结果如下:
T0-P0分配给C0,T0-P1分配给C2,T0-P2分配给C0,
T1-P0分配给C1,T1-P1分配给C0,
T2-P0分配给C1,T2-P1分配给C2,T2-P2分配给C1,T0-P3分配给C2;
推算过程:
分区T0-P0,消费者C0,C0订阅了这个分区所在Topic即T0,所以T0-P0分配给C0;
轮询到下一个分区T0-P1和下一个消费者C1;
分区T0-P1,消费者C1,C1没有订阅T0,取下一个消费者C2,C2订阅了T0,所以T0-P1分配给C2;
轮询到下一个分区T0-P2和下一个消费者C0;
分区T0-P2,消费者C0,C0订阅了T0,所以T0-P2分配给C0;
轮询到下一个分区T1-P0和下一个消费者C1;
分区T1-P0,消费者C1,C1订阅T1,所以T1-P0分配给C1;
以此类推即可。
3.自定义分配策略:实现AbstractPartitionAssignor类的assign()方法
Replication副本分配算法例如以下:
将全部N Broker和待分配的i个Partition排序.
将第i个Partition分配到第(i mod n)个Broker上.
将第i个Partition的第j个副本分配到第((i + j) mod n)个Broker上.
Rebalance的执行
Reblance本质上是一种协议,规定了一个Consumer Group下的所有的Consumer如何达成一致来分配订阅Topic的每个Partition。比如某个group下有5个consumer,它订阅了一个具有10个分区的topic。正常情况下,Kafka平均会为每个consumer分配2个分区。这个分配的过程就叫rebalance。
Rebalance的触发条件:
1.有新的消费者加入Consumer Group
2.有消费者下线,可能由于长时间未向GroupCoordinator(协调者)发送心跳,GroupCoordinator会认为其已下线
3.有消费者主动退出Consumer Group
4.订阅的topic分区出现变化
5.调用unsubscribe()取消对某Topic的订阅
即Consumer或者Topic自身发生变化时,会触发Rebalance。