渐进式rebalance
第一步:所有成员都向coordinator发送请求,请求入组。一旦所有成员都发送了请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader。
第二步:leader开始分配消费方案,指明具体哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案发给coordinator。coordinator接收到分配方案之后会把方案发给各个consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。
(2)以下的场景会触发Consumer Rebalance操作:
①新的消费者加入Consumer Group;②有消费者主动退出Consumer Group;③Consumer Group订阅的任何一个Topic出现分区数量的变化。
(3)默认情况下,Kafka提供了两种分配策略:
Range
和
RoundRobin
。
Range策略
:①对一个topic中的partition进行排序;②对消费者按字典进行排序;③遍历排序后的partition的方式分配给消费者。
例子:有两个消费者C0和C1,两个topic(t0,t1),每个topic有三个分区p(0-2),那么采用Range策略,分配出的结果为:
C0: [t0-p0, t0-p1, t1-p0, t1-p1]
C1: [t0-p2, t1-p2]
RoundRobin
策略:RoundRobin策略和Range策略类型,唯一的区别就是
Range策略分配partition时,是按照topic逐次划分的
。
RoundRobin策略则是将所有topic的所有分区一起排序,然后遍历partition分配给消费者
。
例子:有两个消费者C0和C1,两个topic(t0,t1),每个topic有三个分区p(0-2),那么采用RoundRobin策略,分配出的结果为:
C0: [t0-p0, t0-p2, t1-p1]
C1: [t0-p1, t1-p0, t1-p2]
(4)Kafka对消息的分配是以Partition为单位分配的,而非以每一条消息作为分配单元。这样设计的劣势:无法保证同一个Consumer Group里的Consumer均匀消费数据。优势:①每个Consumer不用都跟大量的Broker通信,减少通信开销;②降低了分配难度,实现也更简单;③因为同一个Partition里的数据是有序的,这种设计可以保证每个Partition里的数据可以被有序消费。
如果某Consumer Group中Consumer实例数量少于Partition数量,则至少有一个Consumer会消费多个Partition的数据,如果Consumer的数量与Partition数量相同,则正好一个Consumer消费一个Partition的数据。而如果Consumer的数量多于Partition的数量时,会有部分Consumer无法消费该Topic下任何一条消息。
3.非线程安全的Kafka Consumer实现多线程消费
(1)线程封闭,即为每个线程实例化一个Consumer对象。说明:一个线程对应一个Consumer 实例,称之为消费线程。一个消费线程可以消费一个或多个分区中的消息,所有的消费线程都隶属于同一个消费组。