分区在集群中的分配策略
- 将所有broker(n个)和partition排序
将第i个Partition分配到第(i mode n)个broker上
Producer如何把消息发送给对应分区
- 当key为空时,消息随机发送到各个分区(各个版本会有不同,有的是采用轮询的方式,有的是随机,有的是一定时间内只发送给固定partition,隔一段时间后随机换一个)
- 用key的ha’sh值对partion个数取模,决定要把消息发送到哪个partition上
消费者分区分配策略
Range 范围分区(默认的)
假如有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多消费了两个分区
RoundRobin 轮询分区
把所有的partition和consumer列出来,然后轮询consumer和partition,尽可能的让把partition均匀的分配给consumer
假如有3个Topic T0(三个分区P0-0,P0-1,P0-2),T1(两个分区P1-0,P1-1),T2(四个分区P2-0,P2-1,P2-2,P2-3)
有三个消费者:C0(订阅了T0,T1),C1(订阅了T1,T2),C2(订阅了T0,T2)
那么分区过程如下图所示
分区将会按照一定的顺序排列起来,消费者将会组成一个环状的结构,然后开始轮询。
P0-0分配给C0
P0-1分配给C1但是C1并没订阅T0,于是跳过C1把P0-1分配给C2,
P0-2分配给C0
P1-0分配给C1,
P1-1分配给C0,
P2-0分配给C1,
P2-1分配给C2,
P2-2分配给C1,
p2-3分配给C2
C0: P0-0,P0-2,P1-1
C1:P1-0,P2-0,P2-2
C2:P0-1,P2-1,P2-3
什么时候触发分区分配策略:
1.同一个Consumer Group内新增或减少Consumer
2.Topic分区发生变化
Rebalance的执行
kafka提供了一个角色Coordinator来执行。当Consumer Group的第一个Consumer启动的时候,他会向kafka集群中的任意一台broker发送GroupCoordinatorRequest请求,broker会返回一个负载最小的broker设置为coordinator,之后该group的所有成员都会和coordinator进行协调通信
整个Rebalance分为两个过程 jionGroup和sysncJion
joinGroup过程
在这一步中,所有的成员都会向coordinator发送JionGroup请求,请求内容包括group_id,member_id.protocol_metadata等,coordinator会从中选出一个consumer作为leader,并且把组成员信息和订阅消息,leader信息,rebanlance的版本信息发送给consumer
Synchronizing Group State阶段
组成员向coordinator发送SysnGroupRequet请求,但是只有leader会发送分区分配的方案(分区分配的方案其实是在消费者确定的),当coordinator收到leader发送的分区分配方案后,会通过SysnGroupResponse把方案同步到各个consumer中