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 ...
随机推荐
- 2. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml
目录 堪比JMeter的.Net压测工具 - Crank 入门篇 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml 堪比JMeter的.Net压测工具 - Crank 进阶篇 ...
- 对称加密算法之DES算法
数据加密标准(data encryption standard): DES是一种分组加密算法,输入的明文为64位,密钥为56位,生成的密文为64位. DES对64位的明文分组进行操作.通过一个初始置换 ...
- 网络之IP地址、子网掩码、网关关联
IP地址?子网掩码? 网关?我们经常混淆这些知识,同时面试的时候又容易被问.下面我们就一个一个的来介绍他们的区别和用途. 网络无处不在,深深影响着我们的生活.而下面几点知识是我们在网络学习中经常遇到的 ...
- kubernetes配置使用ceph动态存储
在k8s集群中配置ceph 3.1.使用cephfs (1) 在ceph集群创建cephfs #以下操作在ceph集群的admin或者mon节点上执行 #创建pool来存储数据和元数据 ceph os ...
- 洛谷训练P1008(循环+暴力)
1 #include<stdio.h> 2 #include<string.h> 3 int a[10]; 4 int main(){ 5 for (int x=123;x&l ...
- @Async的用法和示例
@Async 注解的用法和示例 目录 @Async 注解的用法和示例 背景 异步调用 @Async介绍 在Spring中启用@Async 示例一:基本使用方式 示例二:在同一个类中调用异步方法 示例三 ...
- Go redis hash存储结构体
需求 需要存储用户数据到redis,结构是hash. 然后取出来,自动转成结构体. 结构体 type UserCache struct { Id int64 `json:"id"` ...
- python+pytest接口自动化(6)-请求参数格式的确定
我们在做接口测试之前,先需要根据接口文档或抓包接口数据,搞清楚被测接口的详细内容,其中就包含请求参数的编码格式,从而使用对应的参数格式发送请求.例如某个接口规定的请求主体的编码方式为 applicat ...
- MySQL从卸载到安装!图文详细版(你想知道的全都有!!)
2. MySQL的下载.安装.配置 2.1 MySQL的四大版本 MySQL Community Server社区版本,开源免费,自由下载,但不提供官方技术支持,适用于大多数普通用户. MySQL E ...
- 一比一还原axios源码(二)—— 请求响应处理
上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...