摘要:KafkaProducer在发送消息的时候,需要指定发送到哪个分区, 那么这个分区策略都有哪些呢?

本文分享自华为云社区《Kafka生产者3中分区分配策略》,作者:石臻臻的杂货铺。

KafkaProducer在发送消息的时候,需要指定发送到哪个分区, 那么这个分区策略都有哪些呢?我们今天来看一下

使用分区策略的配置:

1. DefaultPartitioner 默认分区策略

全路径类名:org.apache.kafka.clients.producer.internals.DefaultPartitioner

  • 如果消息中指定了分区,则使用它
  • 如果未指定分区但存在key,则根据序列化key使用murmur2哈希算法对分区数取模。
  • 如果不存在分区或key,则会使用粘性分区策略,关于粘性分区请参阅 KIP-480。

粘性分区Sticky Partitioner

为什么会有粘性分区的概念?

首先,我们指定,Producer在发送消息的时候,会将消息放到一个ProducerBatch中, 这个Batch可能包含多条消息,然后再将Batch打包发送。关于这一块可以看看我之前的文章 图解Kafka Producer 消息缓存模型。

这样做的好处就是能够提高吞吐量,减少发起请求的次数。

但是有一个问题就是, 因为消息的发送它必须要你的一个Batch满了或者linger.ms时间到了,才会发送。如果生产的消息比较少的话,迟迟难以让Batch塞满,那么就意味着更高的延迟。

在之前的消息发送中,就将消息轮询到各个分区的, 本来消息就少,你还给所有分区遍历的分配,那么每个ProducerBatch都很难满足条件。

那么假如我先让一个ProducerBatch塞满了之后,再给其他的分区分配是不是可以降低这个延迟呢?

详细的可以看看下面这张图

这张图的前提是:

Topic1 有3分区, 此时给Topic1 发9条无key的消息, 这9条消息加起来都不超过batch.size .

那么以前的分配方式和粘性分区的分配方式如下

可以看到,使用粘性分区之后,至少是先把一个Batch填满了发送然后再去填充另一个Batch。不至于向之前那样,虽然平均分配了,但是导致一个Batch都没有放满,不能立即发送。这不就增大了延迟了吗(只能通过linger.ms时间到了才发送)

划重点:

  1. 当一个Batch发送之后,需要选择一个新的粘性分区的时候
    ①. 可用分区<1 ;那么选择分区的逻辑是在所有分区中随机选择。
    ②. 可用分区=1; 那么直接选择这个分区。
    ③. 可用分区>1 ; 那么在所有可用分区中随机选择。
  2. 当选择下一个粘性分区的时候,不是按照分区平均的原则来分配。而是随机原则(当然不能跟上一次的分区相同)

例如刚刚发送到的Batch是 1号分区,等Batch满了,发送之后,新的消息可能会发到2或者3, 如果选择的是2,等2的Batch满了之后,下一次选择的Batch仍旧可能是1,而不是说为了平均,选择3分区。

2.UniformStickyPartitioner 纯粹的粘性分区策略

全路径类名:org.apache.kafka.clients.producer.internals.UniformStickyPartitioner

他跟DefaultPartitioner 分区策略的唯一区别就是。

DefaultPartitionerd 如果有key的话,那么它是按照key来决定分区的,这个时候并不会使用粘性分区
UniformStickyPartitioner 是不管你有没有key, 统一都用粘性分区来分配。

3. RoundRobinPartitioner 分区策略

全路径类名:org.apache.kafka.clients.producer.internals.RoundRobinPartitioner

  • 如果消息中指定了分区,则使用它
  • 将消息平均的分配到每个分区中。
  • 与key无关
@Override
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
int nextValue = nextValue(topic);
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
if (!availablePartitions.isEmpty()) {
int part = Utils.toPositive(nextValue) % availablePartitions.size();
return availablePartitions.get(part).partition();
} else {
// no partitions are available, give a non-available partition
return Utils.toPositive(nextValue) % numPartitions;
}
}

上面是具体代码。有个地方需要注意;

  1. 当可用分区是0的话,那么就是遍历的是所有分区中的。
  2. 当有可用分区的话,那么遍历的是所有可用分区的。

点击关注,第一时间了解华为云新鲜技术~

Kafka生成消息时的3种分区策略的更多相关文章

  1. Kafka分区策略

    Kafka分区策略 所谓分区策略是决定生产者将消息发送到哪个分区的算法.Kafka 为我们提供了默认的分区策略,同时它也支持你自定义分区策略. 常见的分区策略包含以下几种:轮询策略.随机策略 .按消息 ...

  2. cassandra框架模型之一——Colum排序,分区策略 Token,Partitioner bloom-filter,HASH

    转自:http://asyty.iteye.com/blog/1202072 一.Cassandra框架二.Cassandra数据模型 Colum / Colum Family, SuperColum ...

  3. kafka的topic和分区策略——log entry和消息id索引文件

    Topic在逻辑上可以被认为是一个在的queue,每条消费都必须指定它的topic,可以简单理解为必须指明把这条消息放进哪个queue里. 为了使得Kafka的吞吐率可以水平扩展,物理上把topic分 ...

  4. 开发测试时给 Kafka 发消息的 UI 发送器――Mikasa

    开发测试时给 Kafka 发消息的 UI 发送器――Mikasa 说来话长,自从入了花瓣,整个人就掉进连环坑了. 后端元数据采集是用 Storm 来走拓扑流程的,又因为 @Zola 不是很喜欢 Jav ...

  5. Kafka的消息格式

    Commit Log Kafka储存消息的文件被它叫做log,按照Kafka文档的说法是: Each partition is an ordered, immutable sequence of me ...

  6. golang实现kafka的消息推送

    Kafka的安装与启动 kafka中涉及的名词 消息记录:由一个key,一个value和一个时间戳构成,消息最终存储在主题下的分区中,记录在生产中称为生产者记录,在消费者中称为消费记录.Kafka集群 ...

  7. Apache Kafka 企业级消息队列

    1.大纲 了解 Apache Kafka是什么 掌握Apache Kafka的基本架构 搭建Kafka集群 掌握操作集群的两种方式 了解Apache Kafka高级部分的内容 2.消息系统的作用是什么 ...

  8. RabbitMQ 和 Kafka 的消息可靠性对比

    RabbitMQ和Kafka都提供持久的消息保证.两者都提供至少一次和至多一次的保证,另外,Kafka在某些限定情况下可以提供精确的一次(exactly-once)保证. 让我们首先理解一下上述术语的 ...

  9. Kafka——分布式消息系统

    Kafka——分布式消息系统 架构 Apache Kafka是2010年12月份开源的项目,采用scala语言编写,使用了多种效率优化机制,整体架构比较新颖(push/pull),更适合异构集群. 设 ...

随机推荐

  1. 通过R Studio用Markdown写Beamer

    技术背景 在写一些学术演示文档时,经常有可能用到Beamer--一种Latex的学术风PPT模板,比如下图所示的这种: 这种风格的演示文档有几个明显的优点:简约.严肃.可以用Latex敲公式和推导.可 ...

  2. redis事务及相关命令介绍

    redis事务及相关命令介绍 一.概述:和众多其它数据库一样,Redis作为NoSQL数据库也同样提供了事务机制.在Redis中,MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事 ...

  3. Tomcat配置Context.xml上下文遇到的坑

    注意事项: 1. 在主机的 appBase 之外找到 WAR 和/或目录,并使用带有 docBase 属性的 context.xml 文件来定义它.避免双重部署导致出现不可预知的问题 {context ...

  4. Mac安装swoole中遇到的问题

    转:https://blog.csdn.net/lishanleilixin/article/details/96137272 1:下载swoole源码,https://github.com/swoo ...

  5. 树莓派系统安装(ubuntu版本)无需屏幕

    0.前提 所需物品:一个手机.一台电脑.一个树莓派.一张tf卡和一个读卡器.所需软件:Win32DiskImager.putty还需要ubuntu系统镜像源.这些我都放在百度网盘上了链接:https: ...

  6. 在VisualStudio调试器中使用内存窗口和查看内存分布

    调试模式下内存窗口的使用 在调试期间,"内存"窗口显示应用使用的内存空间.调试器窗口(如"监视"."自动"."局部变量" ...

  7. 开发一个自己的 CSS 框架(四)

    这一节,我们来讲规矩,谈网格,做人可以不要脸,不讲规矩,不讲道理(特指傲娇兽),但底线还是要有的,如同网格一样,不能超出. jeet 这里我们别人封装好的模块,不过呢,我们也会详细介绍一下原理.首先我 ...

  8. W3School 教程整理

    离线版大部分整理自 w3cschool ,少部分整理自 w3school ,由本人整理. 感谢 w3cschool 站长的无私奉献. 由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博 ...

  9. JavaScript作用域链与闭包的理解

    作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域 链的工作原理. 1. 全局作用域(Global Scope) (1)最外层函数和 ...

  10. python-你好

    你的程序会读入一个名字,比如John,然后输出"Hello John". 输入格式: 一行文字. 输出格式: 一行文字. 输入样例: Mary Johnson 输出样例: Hell ...