kafka指定partiton生产
kafka发送一个消息的时候需要封装成一个ProducerRecord :
public ProducerRecord(String topic, Integer partition, Long timestamp, K key, V value) {
if (topic == null)
throw new IllegalArgumentException("Topic cannot be null");
if (timestamp != null && timestamp < 0)
throw new IllegalArgumentException("Invalid timestamp " + timestamp);
this.topic = topic;
this.partition = partition;
this.key = key;
this.value = value;
this.timestamp = timestamp;
}
我们需要关注的是partition和key。
kafka在调用send的时候实际上是将消息放到了内存中,并没有发送出去。在放到内存队列之前,会计算消息应该放到哪个partiton中
private Future<RecordMetadata> doSend(ProducerRecord<K, V> record, Callback callback) {
// 忽略
int partition = partition(record, serializedKey, serializedValue, metadata.fetch()); // partiton用来计算书消息具体放置的partiton
//忽略
if (result.batchIsFull || result.newBatchCreated) {
log.trace("Waking up the sender since topic {} partition {} is either full or getting a new batch", record.topic(), partition);
this.sender.wakeup();
}
return result.future;
// 忽略
}
我们来分析下partiton方法:
private int partition(ProducerRecord<K, V> record, byte[] serializedKey , byte[] serializedValue, Cluster cluster) {
Integer partition = record.partition(); // ProducerRecord中partiton参数
if (partition != null) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(record.topic());
int lastPartition = partitions.size() - 1;
// they have given us a partition, use it
if (partition < 0 || partition > lastPartition) {
throw new IllegalArgumentException(String.format("Invalid partition given with record: %d is not in the range [0...%d].", partition, lastPartition));
}
return partition; // 指定了partiton,则消息发送到该指定的partiton
}
// 否则使用partitioner根据ProducerRecord的key参数来计算发送的partiton
return this.partitioner.partition(record.topic(), record.key(), serializedKey, record.value(), serializedValue,
cluster);
}
可以通过在配置中指定“partitioner.class”配置项使用自定义的partitioner,自定义的partitioner需要实现Partitioner接口:
public interface Partitioner extends Configurable {
/**
* Compute the partition for the given record.
*
* @param topic The topic name
* @param key The key to partition on (or null if no key)
* @param keyBytes The serialized key to partition on( or null if no key)
* @param value The value to partition on or null
* @param valueBytes The serialized value to partition on or null
* @param cluster The current cluster metadata
*/
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
/**
* This is called when partitioner is closed.
*/
public void close();
}
如果没有指定“partitioner.class”配置项则使用默认的partitioner:DefaultPartitioner。我们来看下DefaultPartitioner的分配方法
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic); // 获取partiton列表,该列表是更新metadata的时候获取的,默认每30s更新一次metadata
int numPartitions = partitions.size();
if (keyBytes == null) { // 如果ProducerRecord没有传入key,则从一个随机数开始,采用round-robin方式
int nextValue = counter.getAndIncrement(); // counter被初始化为一个随机值,每次递增
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
if (availablePartitions.size() > 0) {
int part = DefaultPartitioner.toPositive(nextValue) % availablePartitions.size();
return availablePartitions.get(part).partition();
} else {
// no partitions are available, give a non-available partition
return DefaultPartitioner.toPositive(nextValue) % numPartitions;
}
} else { // 对 keyBytes 进行 hash 选出一个 patition
// hash the keyBytes to choose a partition
return DefaultPartitioner.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
}
kafka指定partiton生产的更多相关文章
- Kafka下的生产消费者模式与订阅发布模式
原文:https://blog.csdn.net/zwgdft/article/details/54633105 在RabbitMQ下的生产消费者模式与订阅发布模式一文中,笔者以“数据接入”和“事 ...
- docker搭建kafka环境&&Golang生产和消费
docker 搭建kafka环境 version: '2' services: zk1: image: confluentinc/cp-zookeeper:latest hostname: zk1 c ...
- 关于怎么获取kafka指定位置offset消息(转)
1.在kafka中如果不设置消费的信息的话,一个消息只能被一个group.id消费一次,而新加如的group.id则会被“消费管理”记录,并指定从当前记录的消息位置开始向后消费.如果有段时间消费者关闭 ...
- ELK+kafka+filebeat搭建生产ELFK集群
文章原文 ELK 架构介绍 集群服务版本 服务 版本 java 1.8.0_221 elasticsearch 7.10.1 filebeat 7.10.1 kibana 7.10.1 logstas ...
- python操作kafka(confluent_kafka 生产)
#!/usr/bin/python # -*- coding:utf-8 -*- from confluent_kafka import Producer import json import tim ...
- kafka指定partition的分区规则
博客地址:https://www.cnblogs.com/gnivor/p/5318319.html
- Python 基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控
基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控 By: 授客 QQ:1033553122 1.测试环境 python 3.4 zookeeper- ...
- 二十二、Hadoop学记笔记————Kafka 基础实战 :消费者和生产者实例
kafka的客户端也支持其他语言,这里主要介绍python和java的实现,这两门语言比较主流和热门 图中有四个分区,每个图形对应一个consumer,任意一对一即可 获取topic的分区数,每个分区 ...
- Kafka基础
简介 #概念:消息中间件(消息系统) //消息系统分类: 点对点 消息队列(peer-to-peer) 发布/订阅 消息队列 消费者在消费时,是通过pull ...
随机推荐
- Blazor和Vue对比学习:说在开始前
1.Vue:现代前端三大框架之一(Vue/React/Angualr),基于HTML.CSS和JavaScript,2014年正式对外发布,目前已发展到3.X版本.值得说道的是,Vue的创始人作者是华 ...
- 【基础知识】Intel CPU体系结构|x86是什么意思
看了<计算机系统结构>.<深入理解计算机系统>.<大话处理器>等经典书籍,也在google上搜了一大堆资料,前前后后.断断续续的折腾了一个多月,终于想通了,现在把自 ...
- LayUI使用注意
# layui获取.修改checkbox的值 <input type="checkbox" name="MySwitch" value="x&q ...
- 使用http-server 快速的开启一个静态服务器
在本地安装好了nodejs后我们可以使用一个命令快速开启一个服务器: 命令界面进入到根目录(存放静态网页的文件夹) //方式一 npx http-server //默认 8080端口 //方式二 np ...
- 通过对比语法差异,让会JAVA的你快速学会Kotlin的开源宝藏项目
今天有个小伙伴来问TJ君,说自己JAVA用的贼溜,想再学习下Kotlin,问TJ君上手难不难? 怎么说呢?其实TJ君一直觉得语言这方面,是触类旁通.一通百通的,既然JAVA已经贼溜了,想必学其他的语言 ...
- JAVA——选择,循环,顺序控制结构
目录 一.顺序控制 二.选择控制 2.1分支控制 2.1.1单分支 2.1.2双分支 2.1.3分支控制if-else 2.1.4嵌套分支 2.2switch分支结构 细节讨论 练习 题目1 题目2 ...
- 线上| 10万奖金!Greaterwms/DVAdmin插件开发者现金激励活动
为激励广大开发者创作精神,Greaterwms/DVadmin插件开发者现金激励活动现已上线! 什么是GreaterWMS 完全开源仓储管理软件,遵循Apache License 2.0协议,前后端分 ...
- 1列表展示的SQL,改为:只查询出vip会员,展示在页面上(10分)
模型代码: //会员 public static function member(){ return self::where('status',1)->select(); } 控制器代码: // ...
- NSView subview blocking drag/drop event
原文链接 近期在Mac项目中有一个处理鼠标拖拽事件的需求, 大致处理流程是这样的: 从 NSView 继承得到一个子类 覆盖处理拖拽事件相关方法 注册拖拽事件 开始的时候一切都很正常,直到某次发现拖拽 ...
- CSAPP CH7链接的应用:静动态库制作与神奇的库打桩机制
目录 创建静态库 创建动态库 库打桩机制 编译时打桩: 链接时打桩 运行时打桩 运行时打桩的printf与malloc循环调用debug 使用LD_PRELOAD对任意可执行程序调用运行时打桩 总结 ...