kafka 分区分配策略

前言

在上一篇文章生产者自定义分区策略 我们提到,生产者可以自定义消息的存储分区,那么kafka如何分配这些分区给相应的消费者者呢?我们先带着这样的问题往下看。

思考:为什么一个topic要创建多个partition?

在实际的应用中,每个topic都会创建多个partition,为什么呢?原因如下:
1. 假如说topic_A 只有一个分区,当数据量过大时,我们如何提升消费者的消费能力?
如何提升kafka吞吐量?我们知道,对于同一个组下的消费者来说,每个主题的某个分区
只能让一个消费者进行消费(不同于rabbitmq的消息轮询),这意味着,当消息量过大时,
我们应用程序是无法提升消费能力的,横向扩展是没有意义的,会导致消息积压过得多,
业务数据延迟过大,但是如果我们对一个topic创建多个分区,这个时候,我们的每个消费者
指定不同的分区,不就解决了这样的问题?是的;
2. 在kafka集群中,同一个topic的多个分区,会分配到不同的broker(kafka内部帮我们
实现的,这块后续再聊),这样也便减轻了每个broker上的负载,提升了节点的IO性能;
3. 如果某个broker宕机了,数据分摊后,我们也可以减少数据损失的风险(此处
暂不考虑分区副本机制);

consumer和partition的数量建议

  1. 如果consumer数量大于partition数量,是一种资源的浪费,上边提到过,kafka的设计
    是不允许特定topic的特定partition 进行并发消费的(这里指的是同一个group下的消费者
    不要和多个group搞混了);
  2. 如果consumer数量小于partition数,一个consumer会对应多个partition,避免分配不均匀,最好partition数是consumer的整数倍;
  3. 消息在同一个分区上是有序的,但是如果多个消费者从多个分区进行消费,是无法保证
    有序性的;

思考:什么时候会触发kafka consumer的reblance ?
当出现以下情况时,每个consumer 消费的分区是会发生一次调整的:

  1. 同一个consumer group 内新增了消费者;
  2. 消费者离开当前的 consumer group,比如主动停服或宕机;
  3. topic新增了分区;

分区分配策略

根据上边讲的,我们应该可以猜到,kafka中一定存在某种策略,来决定
同一个组的消费者如何划分partition的;
三种策略:

RangeAssignor(范围分区)
	range策略是针对每个主题的,首先按照topic的分区号进行排序,并对消费者按照名称
的字典序排序,然后为每个消费者划分固定的分区范围,如果无法平均分配,字典序靠
前的消费者会多分配一个分区。
	假设 n=分区数/消费者数量,m=分区数%消费者数量,那么前m个消费者每个分配n+1个
分区,后面的(消费者数-m)个消费者每个分配n个分区。
	假设我们有10个分区,3个消费者,排完序的分区将会是0, 1, 2, 3, 4, 5, 6, 
7, 8, 9;消费者线程排完序将 会是C1, C2, C3。然后将partitions的个数除于消费者
线程的总数来决定每个消费者线程消费几个 分区。如果除不尽,那么前面几个消费
者线程将会多消费一个分区。在我们的例子里面,我们有10个分 区,3个消费者线
程, 10 / 3 = 3,而且除不尽,那么消费者线程 C1 将会多消费一个分区,即就是:
C1 消费: 0,1,2,3
C2 消费: 4,5,6
C3 消费: 7,8,9
	如果有2个主题(T1和T2),分别有10个分区,那么最后的分配结果是:
C1 消费 T1主题的0,1,2,3 分区以及T2主题的0,1,2,3
C2 消费 T1主题的4,5,5 分区以及T2主题的4,5,6
C3 消费 T1主题的7,8,9 分区以及T2主题的7,8,9
可以看出C1 比其他消费者多了2个分区,这就是Range strategy的一个很明显的弊端。
RoundRobinAssignor(轮询分区)
	轮询分区策略是把所有partition和所有consumer线程都列出来,然后按照hashcode
进行排序。最后通过轮询算法分配partition给消费线程。如果所有consumer实例的订阅
是相同的,那么partition会均匀分布。
	假如T1有10个分区,按照 hashCode 排序完的topic-partitions组依次为T1-5, T1-3, T1-0, 
T1-8, T1-2, T1-1, T1-4, T1-7, T1-6, T1-9,我们的消费者线程排序为C1, C2,最后分区
分配的结果 为:
C1 将消费 T1-5, T1-0, T1-2, T1-4, T1-6 分区; 
C2 将消费 T1-3, T1-8, T1-1, T1-7, T1-9 分区;

**如果同一个消费组内的消费者订阅的信息不同,那么在执行分区分配的时候,就不是
完全的轮询分配,有可能会导致分区分配的不均匀,如果某个消费者没有订阅消费组内的
某个主题,分配分区时,次消费者将分配不到这个主题的任何分区**
StickyAssignor(粘滞分配策略)
特性:
1. 分区的分配尽可能的均匀;
2. 分区的分配尽可能的和上次分配保持一致;
当两者发生冲突时,优先满足第一个目标

	假设消费组有3个消费者:C0,C1,C2,它们分别订阅了2个Topic(T1,T2),并且每个
主题有4个分区(P1,P2,P3,P4),也就是说,整个消费组订阅了8个分区:T1P1、T1P2、
T1P3、T1P4、T2P1、T2P2、T2P3、T2P4, 那么最终的分配场景结果为 :
C0: T1P1, T1P4, T2P3
C1: T1P2, T2P1, T2P4
C2: T1P3, T2P2
	这种分配方式有点类似于轮询策略,但实际上不然,假设C1消费者此时宕机,会导致
重新分区,如果是轮询,那么结果应该是:
C0: T1P1, T1P3, T2P1, T2P3
C2: T1P2, T1P4, T2P2, T2P4
如果是stickyAssignor, 它会满足分区分配尽可能和上次分配保持相同, 那么结果是:
C0: T1P1, T1P4, T2P3, T1P2
C2: T1P3, T2P2, T2P1, T2P4
减少了不必要的分区移动
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值