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生产的更多相关文章

  1. Kafka下的生产消费者模式与订阅发布模式

    原文:https://blog.csdn.net/zwgdft/article/details/54633105   在RabbitMQ下的生产消费者模式与订阅发布模式一文中,笔者以“数据接入”和“事 ...

  2. docker搭建kafka环境&&Golang生产和消费

    docker 搭建kafka环境 version: '2' services: zk1: image: confluentinc/cp-zookeeper:latest hostname: zk1 c ...

  3. 关于怎么获取kafka指定位置offset消息(转)

    1.在kafka中如果不设置消费的信息的话,一个消息只能被一个group.id消费一次,而新加如的group.id则会被“消费管理”记录,并指定从当前记录的消息位置开始向后消费.如果有段时间消费者关闭 ...

  4. ELK+kafka+filebeat搭建生产ELFK集群

    文章原文 ELK 架构介绍 集群服务版本 服务 版本 java 1.8.0_221 elasticsearch 7.10.1 filebeat 7.10.1 kibana 7.10.1 logstas ...

  5. python操作kafka(confluent_kafka 生产)

    #!/usr/bin/python # -*- coding:utf-8 -*- from confluent_kafka import Producer import json import tim ...

  6. kafka指定partition的分区规则

    博客地址:https://www.cnblogs.com/gnivor/p/5318319.html

  7. Python 基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控

    基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控   By: 授客 QQ:1033553122   1.测试环境 python 3.4 zookeeper- ...

  8. 二十二、Hadoop学记笔记————Kafka 基础实战 :消费者和生产者实例

    kafka的客户端也支持其他语言,这里主要介绍python和java的实现,这两门语言比较主流和热门 图中有四个分区,每个图形对应一个consumer,任意一对一即可 获取topic的分区数,每个分区 ...

  9. Kafka基础

    简介 #概念:消息中间件(消息系统)      //消息系统分类:         点对点 消息队列(peer-to-peer)         发布/订阅 消息队列 消费者在消费时,是通过pull ...

随机推荐

  1. linux安装ngixn

    卸载ngxin(第一次安装请略过) 1.检查nginx是否启动,是否安装ngxin 检查是否安装nginx命令 rpm -qa|grep nginx 检查nginx是否启动命令: pa -ef|gre ...

  2. linux的分区方法

    linux分区方法,不同的人有不同的方法,反正没有统一的方法.在分区方面,我觉得根据自己的实际情况来分是最好的.玩linux也有好几年了,下面说一下,我在分区方面的一些经验. 一,个人用 如果是个人用 ...

  3. C# Task和异步方法

    本文主要参考: https://www.cnblogs.com/qtiger/p/13497807.html ThreadPool中有若干数量的线程.当有任务需要处理时,会从线程池中获取一个空闲的线程 ...

  4. 小白文-SpringMVC-解读DispatcherServlet源码

    SpringMVC 学习完Spring框架技术之后,差不多会出现两批人: 一批是听得云里雾里,依然不明白这个东西是干嘛的: 还有一批就是差不多理解了核心思想,但是不知道这些东西该如何去发挥它的作用. ...

  5. Qt:QVector

    0.说明 template <typename T> class QVector QVector是存储同一个类型T数据的模板类,其功能是动态数组,数据在其中的存储是一系列连续的存储空间. ...

  6. redis数据类型的使用及介绍

    Redis数据类型 1.Sting类型 set命令 设置键值,存在则覆盖,不存在则新建 set key value EX 秒 设置有效时长为秒 nx 如果键不存在则新建,如果存在返回nil xx 只有 ...

  7. 使用Dapper访问SQL Server数据库

    对应Demo程序名:DapperDemo 准备工作:为项目安装Dapper类库 方法一:项目中添加:项目名右键:Manage NuGet Packages:搜索Dappe:点击安装 方法二:在NuGe ...

  8. Excel用Power Query把文件夹下所有文件合并为一个与合并多个表格

    Excel用Power Query把文件夹下所有文件合并为一个与合并多个表格 在 Excel Power Query 未出来之前,把文件夹下所有文件合并为一个与合并同一工作表中的多个工作表,需要用 V ...

  9. ospf应用简单

    ospf应用简单 OSPF (SPF) 属于链路状态路由选择协议,并且是公有标准, 理论上是没有网络规模限制的: 支持网络的层次化设计,可以将网络分为2层.   层,是通过"区域" ...

  10. NTFS权限详解

    NTFS权限是作为一个Windows管理员必备的知识,许多经验丰富的管理员都能够很熟悉地对文件.文件夹.注册表项等进行安全性的权限设置,包括完全控制.修改.只读等.而谈论NTFS权限这个话题也算是老生 ...