众所周知,Apache Kafka是基于生产者和消费者模型作为开源的分布式发布订阅消息系统(当然,目前Kafka定位于an open-source distributed event streaming platform),由Scala和Java编写。

Kafka提供了类似于JMS的特性,但设计上又有很大区别,它不是JMS规范的实现,如Kafka允许多个消费者主动拉取数据,而在JMS中只有点对点模式消费者才会主动拉取数据。

Kafka producer在向Kafka集群发送消息时,需要指定topic,Kafka根据topic对消息进行归类(逻辑划分),而一个topic通常会有多个partition分区,落到磁盘上就是多个partition目录。

Kafka consumer为了及时消费消息,会以Consumer Group(消费组)的形式,启动多个consumer消费消息。不同的消费组在消费消息时彼此互不影响,同一个消费组的consumer协调在一起消费订阅的topic所有分区消息。这就引申一个问题:消费组中的consumer是如何确定自己该消费哪些分区的数据的?

Kafka提供了多种分区策略如RoundRobin(轮询)、Range(按范围),可通过参数partition.assignment.strategy进行配置。

一般情况下,在topic和消费组不发生变化,Kafka会根据topic分区、消费组情况等确定分区策略,但是当发生以下情况时,会触发Kafka的分区重分配:

1. Consumer Group中的consumer发生了新增或者减少

  1. 同一个Consumer Group新增consumer
  2. Consumer Group订阅的topic分区发生变化如新增分区

2. Consumer Group订阅的topic分区发生变化如新增分区

本文通过下面的场景,来分别阐述Kafka主要的分配策略RoundRobin和Range:

Range Strategy

Range策略是针对topic而言的,在进行分区分配时,为了尽可能保证所有consumer均匀的消费分区,会对同一个topic中的partition按照序号排序,并对consumer按照字典顺序排序。

然后为每个consumer划分固定的分区范围,如果不够平均分配,那么排序靠前的消费者会被多分配分区。具体就是将partition的个数除于consumer线程数来决定每个consumer线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多分配分区。

通过下面公式更直观:

假设n = 分区数 / 消费者数量,m = 分区数 % 消费者线程数量,那么前m个消费者每个分配n+1个分区,后面的(消费者线程数量 - m)个消费者每个分配n个分区。

举个例子:

一个消费组CG1中有C0和C1两个consumer,消费Kafka中的主题t1。t1的分区数为10,并且C1的num.streams为1,C2的num.streams为2。

经过排序后,分区为:0, 1, 2, 3, 4, 5, 6, 7, 8, 9;CG1中消费者线程为C0-0、C1-0、C1-1。然后因为 10除3除不尽,那么消费者线程C0-0将会多分配分区,所以分区分配之后结果如下:

C0-0 将消费0、1、2、3分区
C1-0 将消费4、5、6分区
C1-1 将消费7、8、9分区

当存在有2个Kafka topic(t1和t2),它们都有有10个partition,那么最后分区结果为:

C0-0 将消费t1主题的0、1、2、3分区以及t2主题的0、1、2、3分区
C1-0 将消费t1主题的4、5、6分区以及t2主题的4、5、6分区
C2-1 将消费t1主题的7、8、9分区以及t2主题的7、8、9分区

如上场景,随着topic的增多,那么针对每个topic,消费者C0-0都将多消费1个分区,topic越多比如为N个,C0-0消费的分区会比其他消费者明显多消费N个分区。

可以明显的看到这样的分配并不均匀,如果将类似的情形扩大,有可能会出现部分消费者过载的情况,这就是Range分区策略的一个很明显的弊端。

RoundRobin Strategy

RoundRobin策略的工作原理:将所有topic的partition组成TopicAndPartition列表,然后对TopicAndPartition列表按照hashCode进行排序:

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风格将分区分别分配给不同的消费者。

使用RoundRobin策略必须满足以下条件:

1.同一个Consumer Group里面的所有consumer的num.streams必须相等

2.每个consumer订阅的topic必须相同

假设消费组CG1中有C0和C1两个consumer的num.streams都为2。按照hashCode排序完的topic-partition组依次为t1-5, t1-3, t1-0, t1-8, t1-2, t1-1, t1-4, t1-7, t1-6, t1-9,我们的消费者排序为C0-0, C0-1, C1-0, C1-1,最后分区分配的结果为:

C0-0将消费t1-5、t1-2、t1-6分区
C0-1将消费t1-3、t1-1、t1-9分区
C1-0将消费t1-0、t1-4分区
C1-1将消费t1-8、t1-7分区

多个主题的分区分配和单个主题类似,这里就不在介绍了。

上面RoundRobin要求每个consumer订阅的topic必须相同,当订阅的topic不同时,那么在执行分区分配的时候就不是完全的轮询分配,有可能会导致分区分配的不均匀。比如,某个consumer没有订阅消费组内的某个topic,那么在分配分区的时候,这个consumer将分配不到这个topic的分区。

除了上述的介绍的RoundRobin和Range分配策略,Kafka还有Sticky分配策略,它主要有两个目的:

  1. 分区的分配要尽可能的均匀
  2. 分区的分配尽可能的与上次分配的保持相同

当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略要复杂很多。


关注 微信公众号:大数据学习与分享,获取更多技术干货

推荐文章:

Kafka作为消息系统的系统补充​mp.weixin.qq.com

分布式流平台Kafka​mp.weixin.qq.com

SparkStreaming和Kafka基于Direct Approach如何管理offset​mp.weixin.qq.com

kafka consumer配置拉取速度慢_Kafka分区分配策略(Partition Assignment Strategy)相关推荐

  1. kafka consumer配置拉取速度慢_Kafka消费者的使用和原理

    这周我们学习下消费者,仍然还是先从一个消费者的Hello World学起: public class Consumer { public static void main(String[] args) ...

  2. Kafka分区分配策略(Partition Assignment Strategy)

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

  3. kafka的分区策略(partition assignment strategy)

    概述 kafka的分区策略指的是producer端的 各个partition中的数据如何安排给consumer消费. Range(按范围) ange策略是对每个主题而言的,首先对同一个主题里面的分区按 ...

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

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

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

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

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

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

  7. Consumer消息拉取和消费流程分析

    1. 前言 MQConsumer是RocketMQ提供的消费者接口,从接口定义上可以看到,它主要的功能是订阅感兴趣的Topic.注册消息监听器.启动生产者开始消费消息. ​ 消费者获取消息的模式有两种 ...

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

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

  9. Kafka 原理以及分区分配策略剖析

    欢迎关注方志朋的博客,回复"666"获面试宝典 ‍ ‍一.简介‍ ‍ Apache Kafka 是一个分布式的流处理平台(分布式的基于发布/订阅模式的消息队列[Message Qu ...

最新文章

  1. iOS端Socket(二)ProtocolBuffer使用
  2. android 组件 线程,Android UI线程和非UI线程
  3. SpringBoot对于标注@ResponseBody注解返回JSON数据的处理
  4. python pipeline框架_介绍Python的Django框架中的静态资源管理器django-pipeline
  5. 130. Surrounded Regions 被围绕的区域
  6. Vue 2升级 Vue 3初探小细节
  7. Linux 命令之 vmstat 命令-显示虚拟内存状态
  8. 产品经理欲哭无泪的瞬间(太真实了)
  9. 作者:温孚江,现任山东农业大学校长、教授,农业大数据创新战略联盟理事长,全国人民代表大会常务委员会委员。...
  10. window java 环境_Windows配置java环境
  11. (4)ZYNQ AXI4总线协议介绍
  12. 七日Python之路--第十一天
  13. linux怎么查看设备序列号,linux 使用dmidecode查看设备序列号
  14. 基于SSM框架的电影订票系统
  15. 读研计算机技术与控制工程比较,电气工程与控制工程研究生考研就业的区别,哪个比较好...
  16. Unity实战篇 | unity接入QQ登录 详细过程——Android篇
  17. 论文笔记—RGB-D SLAM in Dynamic Environments Using Static Point Weighting
  18. linux下安装weblogic出现的两个错误解决办法
  19. 安装Bouncy Castle(JAVA)
  20. GraphicsMagick实现云服务商基础图片处理

热门文章

  1. JaveWeb学习之Servlet(二):ServletConfig和ServletContext
  2. python下载地址
  3. Xcode 6 allows VECTOR image assets… any idea how to use them?
  4. RabbitMQ之比较好的资料
  5. poj 1092 Farmland (Geometry)
  6. C#:如何去掉groupbox的边框线
  7. c# 中的as,is
  8. CentOS7 配置ISCSI targetcli 共享存储
  9. hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)
  10. Java实战之04JavaWeb-02Request和Response