问题

用过 Kafka 的同学用过都知道,每个 Topic 一般会有很多个 partitions。为了使得我们能够及时消费消息,我们也可能会启动多个 Consumer 去消费,而每个 Consumer 又会启动一个或多个streams去分别消费 Topic 里面的数据。我们又知道,Kafka 存在 Consumer Group 的概念,也就是 group.id 一样的 Consumer,这些 Consumer 属于同一个Consumer Group,组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一个消费组内的一个consumer来消费。那么问题来了,同一个 Consumer Group 里面的 Consumer 是如何知道该消费哪些分区里面的数据呢?

如上图,Consumer1 为啥消费的是 Partition0 和 Partition2,而不是 Partition0 和 Partition3?这就涉及到 Kafka 内部分区分配策略(Partition Assignment Strategy)了。

在 Kafka 内部存在两种默认的分区分配策略:Range 和 RoundRobin。当以下事件发生时,Kafka 将会进行一次分区分配:
•同一个 Consumer Group 内新增消费者
•消费者离开当前所属的Consumer Group,包括shuts down 或 crashes
•订阅的主题新增分区

将分区的所有权从一个消费者移到另一个消费者称为重新平衡(rebalance),如何rebalance就涉及到本文提到的分区分配策略。下面我们将详细介绍 Kafka 内置的两种分区分配策略。本文假设我们有个名为 T1 的主题,其包含了10个分区,然后我们有两个消费者(C1,C2)来消费这10个分区里面的数据,而且 C1 的 num.streams = 1,C2 的 num.streams = 2。

Range strategy

Range策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。在我们的例子里面,排完序的分区将会是0, 1, 2, 3, 4, 5, 6, 7, 8, 9;消费者线程排完序将会是C1-0, C2-0, C2-1。然后将partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。在我们的例子里面,我们有10个分区,3个消费者线程, 10 / 3 = 3,而且除不尽,那么消费者线程 C1-0 将会多消费一个分区,所以最后分区分配的结果看起来是这样的:

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

假如我们有11个分区,那么最后分区分配的结果看起来是这样的:

C1-0 将消费 0, 1, 2, 3 分区
C2-0 将消费 4, 5, 6, 7 分区
C2-1 将消费 8, 9, 10 分区

假如我们有2个主题(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个分区,这就是Range strategy的一个很明显的弊端。

RoundRobin strategy

使用RoundRobin策略有两个前提条件必须满足:
•同一个Consumer Group里面的所有消费者的num.streams必须相等;
•每个消费者订阅的主题必须相同。

所以这里假设前面提到的2个消费者的num.streams = 2。RoundRobin策略的工作原理:将所有主题的分区组成 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
})

最后按照round-robin风格将分区分别分配给不同的消费者线程。

在我们的例子里面,加入按照 hashCode 排序完的topic-partitions组依次为T1-5, T1-3, T1-0, T1-8, T1-2, T1-1, T1-4, T1-7, T1-6, T1-9,我们的消费者线程排序为C1-0, C1-1, C2-0, C2-1,最后分区分配的结果为:

C1-0 将消费 T1-5, T1-2, T1-6 分区;
C1-1 将消费 T1-3, T1-1, T1-9 分区;
C2-0 将消费 T1-0, T1-4 分区;
C2-1 将消费 T1-8, T1-7 分区;

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

根据上面的详细介绍相信大家已经对Kafka的分区分配策略原理很清楚了。不过遗憾的是,目前我们还不能自定义分区分配策略,只能通过partition.assignment.strategy参数选择 range 或 roundrobin。partition.assignment.strategy参数默认的值是range。

Kafka分区分配策略(Partition Assignment Strategy)相关推荐

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

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

  2. Kafka分区分配策略(2)——RoundRobinAssignor和StickyAssignor

    接上文[Kafka分区分配策略(1)--RangeAssignor] 欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔 ...

  3. 9.Kafka 分区分配策略(Range分配策略 RoundRobin分配策略)

    前言 在 Kafka 实际生产过程中,每个 topic 都会有 多个 partitions.   1.多个Partitions有什么好处? ①多个 partition ,能够对 broker 上的数据 ...

  4. Kafka分区分配策略(3)——自定义分区分配策略

    接上文: 1.[Kafka分区分配策略(1)--RangeAssignor] 2.[Kafka分区分配策略(2)--RoundRobinAssignor和StickyAssignor] 欢迎支持笔者新 ...

  5. Kafka分区分配策略(4)——分配的实施

    接上文: 1.[Kafka分区分配策略(1)--RangeAssignor] 2.[Kafka分区分配策略(2)--RoundRobinAssignor和StickyAssignor] 3.[Kafk ...

  6. Kafka分区分配策略(1)——RangeAssignor

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

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

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

  8. kafka分区分配策略

    kafka的分区分配策略大概可以分为一下几步: 前置条件: a.假设消费者组到对应的server的GroupCordinator是已知的,这个groupCordinator和消费组对应的_offset ...

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

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

最新文章

  1. Ruby中对象数组排序
  2. Spring框架中集合属性为对象的注入方法
  3. Windows网络命令行程序
  4. CCF201312--模拟练习试题参考答案(C++)
  5. mysql 主从宕机切换_mysql主从复制配置操作以及主从宕机切换演练
  6. 拓端tecdat|Python对商店数据进行lstm和xgboost销售量时间序列建模预测分析
  7. Reeder 5 for Mac(RSS阅读器)
  8. JavaScript弹窗事件
  9. Linux学习笔记(五) -- Linux+Anjuta搭建C++开发环境
  10. (~ ̄▽ ̄)~罗马数字图表
  11. Microsoft Edge浏览器不兼容解决办法
  12. iOS - 找出汉字拼音首字母
  13. 微信图片去除马赛克_朋友圈分享技巧 如何快速地截图打马赛克?
  14. 【网络】 输入www.baidu.com后的过程详解
  15. Linux SDIO WIFI Marvell8801/Marvell88w8801(五) --- Linux SDIO API介绍
  16. 载波层叠调制在多电平变换器及两电平变换器中的应用
  17. 【经验】展会结束后跟进客户最佳方案
  18. VMWare软件定义数据中心SDDC
  19. 图纸转图片cad转换成jpg格式
  20. 计算机毕业设计(附源码)python医院疫情管理系统

热门文章

  1. 润乾报表列太多导致渲染速度慢_报表自动化: 如何选择可视化大屏开发利器
  2. js ajax 浏览器兼容,JS跨浏览器兼容,一点点总结
  3. 和sexy_“纸片人”没曲线?Mark这三招,H型身材也能驾驭sexy
  4. VTK:变形3D用法实战
  5. JavaScript实现breadth First Search广度优先搜索算法(附完整源码))
  6. wxWidgets:wxWebView 示例
  7. wxWidgets:wxLayoutAlgorithm类用法
  8. boost::thread模块实现生产者消费者的测试程序
  9. BOOST_PP_IS_EMPTY宏相关的测试程序
  10. boost::io模块ios相关的测试程序