Kafka消费者组三种分区分配策略roundrobin,range,StickyAssignor

文章目录

  • Kafka消费者组三种分区分配策略roundrobin,range,StickyAssignor
    • 1. Range(默认策略)
    • 2. RoundRobin
    • 3. StickyAssignor

一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。

Kafka有三种分配策略,roundrobin Assignor,range Assignor,Sticky Assignor

将分区的所有权从一个消费者移到另一个消费者称为重新平衡(rebalance)。当以下事件发生时,Kafka 将会进行一次分区分配:

  • 同一个 Consumer Group 内新增消费者
  • 消费者离开当前所属的Consumer Group,包括shuts down 或 crashes
  • 订阅的主题新增分区

目前还不能自定义分区分配策略,只能通过partition.assignment.strategy参数,设置 消费者 与 订阅主题 之间的分区分配策略,默认使用 RangeAssignor 分配策略,此参数partition.asssignment.strategy可以配置多个分配策略,彼此之间以逗号分隔。

1. Range(默认策略)

2.4.x版本官方介绍:

http://kafka.apache.org/24/javadoc/org/apache/kafka/clients/consumer/RangeAssignor.html

Range:是以Topic为单位,首先,对同一个Topic里的分区,按照序号进行排序,并对消费者按照字母顺序进行排序。然后用Partitions分区的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。

大致估算每个消费者分配多少个分区 n = 分区数/消费者数量(n:分配的分区个数)

若除不尽,则取余数 m = 分区数 % 消费者数量,表示前 m 个消费者每个分配 n+1 个分区(即多分配一个分区),剩余的消费者(消费者数量 减去 m)每个分配 n 个分区。

有10个分区,3个消费者线程,把分区按照序号排列0,1,2,3,4,5,6,7,8,9;消费者线程为C1-0,C2-0,C2-1。

例如,有10个分区,3个消费者线程,10/3 = 3,除不尽,10%3=1,那么消费者线程C1-0将会多消费一个分区:

C1-0:0,1,2,3
C2-0:4,5,6
C2-1:7,8,9

如果有11个分区,则11%3=2,表示前面两个消费者多分配一个分区:
C1-0:0,1,2,3
C2-0:4,5,6,7
C2-1:8,9,10

假如有两个主题T1,T2,分别有10个分区,最后的分配结果将是这样:

C1-0:T1(0,1,2,3) T2(0,1,2,3)
C2-0:T1(4,5,6) T2(4,5,6)
C2-1:T1(7,8,9) T2(7,8,9)

可以看出, C1-0消费者线程比其他消费者线程多消费了2个分区

如上,只是针对 1 个 topic 而言,C1-0消费者多消费1个分区影响不是很大。如果有 N 多个 topic,那么针对每个 topic,消费者 C1-0 都将多消费 1 个分区,topic越多,C1-0 消费的分区 会比其他消费者 明显多消费 N 个分区。这就是 Range 范围分区的一个很明显的弊端了

2. RoundRobin

2.4.x版本官方介绍:

http://kafka.apache.org/24/javadoc/org/apache/kafka/clients/consumer/RoundRobinAssignor.html

RoundRobin:是以消费者组为单位,将消费者组内 所有消费者 以及消费者订阅的 所有topic的分区 按字典序排序,然后通过轮询方式,逐个将分区分配给每个消费者。

使用RoundRobin策略有两个前提条件必须满足:

  1. 同一个消费者组里的 所有消费者的num.streams(消费者消费线程数)必须相等;
  2. 每个消费者订阅的主题必须相同。

假设2个消费者的num.streams = 2。RoundRobin策略的工作原理:将所有主题的分区组成 TopicAndPartition 列表,然后对TopicAndPartition 列表按照 hashCode 进行排序,最后按照roundrobin模式,将分区分别分配给不同的消费者线程。

val allTopicPartitions = ctx.partitionsForTopic.flatMap { case(topic, partitions) =>info("Consumer %s rebalancing the following partitions for topic %s: %s".format(ctx.consumerId, topic, partitions))partitions.map(partition => {TopicAndPartition(topic, partition)})
}.toSeq.sortWith((topicPartition1, topicPartition2) => {/** Randomize the order by taking the hashcode to reduce the likelihood of all partitions of a given topic ending* up on one consumer (if it has a high enough stream count).*/topicPartition1.toString.hashCode < topicPartition2.toString.hashCode
})

RoundRobin的两种情况:

  1. 如果同一个消费组内 所有的消费者订阅的topic 都是一样的,那么RoundRobinr策略的分区分配是均匀的。

假设消费组中有2个消费者 C0 和 C1 ,都订阅了主题 t0 和 t1 ,并且每个主题都有 3个分区,那么所订阅的所有分区可以标识为:t0p0、t0p1、t0p2、t1p0、t1p1、t1p2。最终的分配结果为:

消费者C0:t0p0、t0p2、t1p1
消费者C1:t0p1、t1p0、t1p2

  1. 如果同一个消费组内的消费者 所订阅的topic 是不一样的,那么在执行分区分配的时候,就不是完全的轮询分配,有可能会导致分区分配的不均匀。 如果某个消费者 没有订阅消费组内的某个topic,那么在分配分区的时候,此消费者将分配不到这个topic的任何分区。

假设消费组内有3个消费者C0、C1和C2,它们共订阅了3个主题:t0、t1、t2,这3个主题分别有1、2、3个分区,即整个消费组订阅了t0p0、t1p0、t1p1、t2p0、t2p1、t2p2这6个分区。具体而言,消费者C0订阅的是主题t0,消费者C1订阅的是主题t0、t1,消费者C2订阅的是主题t0、t1、t2,那么最终的分配结果为:

消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2

可以看到RoundRobinAssignor策略也不是十分完美,这样分配其实并不是最优解,因为完全可以将分区t1p1分配给消费者C1。

3. StickyAssignor

2.4.x版本官方介绍:

http://kafka.apache.org/24/javadoc/org/apache/kafka/clients/consumer/StickyAssignor.html

StickyAssignor黏性分区,是0.11.x版本引入的新分配策略,它主要有两个目的:

  1. 分区的分配要尽可能的均匀,分配给消费者者的主题分区数最多相差一个;
  2. 分区的分配尽可能的与上次分配的保持相同。

当两者发生冲突时,第一个目标优先于第二个目标。

假设消费组内有3个消费者:C0、C1和C2,它们都订阅了4个主题:t0、t1、t2、t3,并且每个主题有2个分区,也就是说整个消费组订阅了t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1这8个分区。最终的分配结果如下:

消费者C0:t0p0、t1p1、t3p0
消费者C1:t0p1、t2p0、t3p1
消费者C2:t1p0、t2p1

这样看上去似乎与采用RoundRobinAssignor策略所分配的结果相同,但实际并非如此

此时假设消费者C1脱离了消费组,那么消费组就会执行再平衡操作,进而消费分区会重新分配。如果采用RoundRobin策略,那么此时的分配结果如下:

消费者C0:t0p0、t1p0、t2p0、t3p0
消费者C2:t0p1、t1p1、t2p1、t3p1

如分配结果所示,RoundRobin策略会按照消费者C0和C2进行重新轮询分配。而如果此时使用的是StickyAssignor策略,那么分配结果为:

消费者C0:t0p0、t1p1、t3p0、t2p0
消费者C2:t1p0、t2p1、t0p1、t3p1

可以看到分配结果中,保留了上一次分配中对于消费者C0和C2的所有分配结果,并将原来消费者C1消费的分区,分配给了剩余的两个消费者C0和C2,最终C0和C2的分配还保持了均衡。

如果发生分区重分配,那么对于同一个分区而言有可能之前的消费者和新指派的消费者不是同一个,对于之前消费者进行到一半的处理还要在新指派的消费者中再次复现一遍,这显然很浪费系统资源。StickyAssignor策略如同其名称中的“sticky”一样,让分配策略具备一定的“粘性”,尽可能地让前后两次分配相同,进而减少系统资源的损耗以及其它异常情况的发生。

若组内消费者订阅的主题不一样的情况如下:

举例,同样消费组内有3个消费者:C0、C1和C2,集群中有3个主题:t0、t1、t2,这3个主题分别有1、2、3个分区,也就是说集群中有t0p0、t1p0、t1p1、t2p0、t2p1、t2p2这6个分区。消费者C0订阅了主题t0,消费者C1订阅了主题t0、t1,消费者C2订阅了主题t0、t1、t2。

如果此时采用RoundRobinAssignor策略,那么最终的分配结果如下所示(和讲述RoundRobinAssignor策略时的一样):

消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2

如果采用的是StickyAssignor策略,那么最终的分配结果为:

消费者C0:t0p0
消费者C1:t1p0、t1p1
消费者C2:t2p0、t2p1、t2p2

可以看到这是一个最优解(消费者C0没有订阅主题t1和t2,所以不能分配主题t1和t2中的任何分区给它,对于消费者C1也可同理推断)。

假如此时消费者C0脱离了消费组,那么RoundRobinAssignor策略的分配结果为:

消费者C1:t0p0、t1p1
消费者C2:t1p0、t2p0、t2p1、t2p2

可以看到RoundRobinAssignor策略保留了消费者C1和C2中原有的3个分区的分配:t2p0、t2p1和t2p2(针对结果集1)。而如果采用的是StickyAssignor策略,那么分配结果为:

消费者C1:t1p0、t1p1、t0p0
消费者C2:t2p0、t2p1、t2p2

可以看到StickyAssignor策略保留了消费者C1和C2中原有的5个分区的分配:t1p0、t1p1、t2p0、t2p1、t2p2。

从结果上看StickyAssignor策略比另外两者分配策略而言显得更加的优异。

Kafka-消费者组三种分区分配策略Range Assignor、RoundRobin Assignor、Sticky Assignor详细解析相关推荐

  1. 【Kafka】Kafka消费者组三种分区分配策略roundrobin,range,StickyAssignor

    文章目录 1. 分配策略 1.1 Range(默认策略) 1.2 RoundRobin RoundRobin的两种情况 1.3 StickyAssignor 2. Range策略演示 参考 相关文章 ...

  2. Kafka消费者组三种分区分配策略roundrobin,range,StickyAssignor

    一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消 ...

  3. 深入分析Kafka架构(三):消费者消费方式、三种分区分配策略、offset维护

    本文目录 一.前言 二.消费者消费方式 三.分区分配策略 3.1.分配分区的前提条件 3.2.Range分配策略 3.3.RoundRobin分配策略 3.4.Sticky分配策略 四.offset维 ...

  4. Kafka Range、RoundRobin、Sticky 三种 分区分配策略区别

    Kafka Range RoundRobin 和Sticky 三种 分区分配策略 一.Kafka默认分区分配策略 1.1 consumer 订阅 1 topic ( 7 partition ) 按照K ...

  5. 深入浅出系列之 -- kafka消费者的三种语义模型

    本文主要详解kafka client的使用,包括kafka消费者的三种消费语义at-most-once,at-least-once,和exact-once message,生产者的使用等. 创建主题 ...

  6. 【kafka】Kafka消费者分区分配策略详解

    文章目录 1.概述 2.RoundRobinAssignor详解 3.RangeAssignor详解 4.StickyAssignor详解 5.CooperativeStickyAssignor详解 ...

  7. Kafka分区分配策略以及重平衡过程总结

    Kafka自身提供了三种分区分配策略,通过消费者端配置参数partition.assignment.strategy来控制. 1.RangeAssignor分配策略(kafka默认的分区策略) 通过配 ...

  8. Kafka学习-----Kafka消费者Consumer:消费方式,分区分配策略,RangeRoundRobin

    目录 一.消费方式 二.消费者的分配模式 1.分配时机? 2.Range策略 2.RoundRobin 策略 三.代码解释 RangeAssignor: RoundRobinAssignor 一.消费 ...

  9. kafka partition分配_kafka的分区分配策略

    用过 Kafka 的同学应该都知道,每个 Topic 一般会有很多个 partitions.为了使得我们能够及时消费消息,我们也可能会启动多个 Consumer 去消费,而每个 Consumer 又会 ...

最新文章

  1. python3自动释放线程_Python3高级特性:并发
  2. ios10申请权限以及弹出允许使用数据框
  3. 获取init程序的调试信息和uevent的调试信息需要打开的两个宏
  4. Required request body is missing 错误
  5. linux下安装树梅派系统,优麒麟树莓派系统(优麒麟 for Raspberry Pi)的安装方法...
  6. java xmlrpc2.0 实现_简单的java xmlrpc
  7. 【2019牛客暑期多校训练营(第五场)- E】independent set 1(最大独立集,状压dp)
  8. notepad++怎么换行命令_notepad++如何自动换行
  9. 因为一个字符校对问题,我的大厂面试挂了
  10. c语言文件操作函数(未完待续)
  11. SpringBoot 简单实现仿CAS单点登录系统
  12. linux的服务文件,Linux的nfs文件服务
  13. Java 高阶 —— 相等性比较
  14. 解决Latex编译报错:Command `\Bbbk‘ already defined. ...ol{\Bbbk} {\mathord}{AMSb}{“7C}
  15. Android导入第三方类库
  16. FineUI.Grid内容换行处理
  17. 解决SVN汉化不成功问题,下载历史版本
  18. 《C专家编程》读书笔记(1)
  19. Android开发开发时语言对照表
  20. 清理打印机连接数bat_通过批处理bat解决局域网打印机共享问题

热门文章

  1. html table colgroup,关于HTML colgroup标签的用法你知道哪些?colgroup用法和col的详细介绍...
  2. 一、用XAMPP搭建本地PHP服务器,运行php文件
  3. GSMA公布MWC19上海最新信息
  4. scrollTop滚动的时候一直是0
  5. 产品设计体会(3016)一个只有七天的项目
  6. matlab贝塞尔函数重积分,第三章 贝塞尔函数 柱函数.pdf
  7. Linux清屏命令与 Windows清屏命令
  8. 简单自我介绍一下~~~~
  9. H264 i帧p帧b帧详解
  10. redis可视化工具读取数据乱码问题解决