package cn.xiaojf.kafka.producer;

import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.utils.Utils; import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger; /**
* 自定义分区方式
*/
public class CustomPartitioner implements Partitioner {
private final ConcurrentMap<String, AtomicInteger> topicCounterMap = new ConcurrentHashMap(); public CustomPartitioner() {
} public void configure(Map<String, ?> configs) {
} /**
* 自定义分区规则
* @param topic
* @param key
* @param keyBytes
* @param value
* @param valueBytes
* @param cluster
* @return
*/
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
if(keyBytes == null) {
int nextValue = this.nextValue(topic);
List availablePartitions = cluster.availablePartitionsForTopic(topic);
if(availablePartitions.size() > 0) {
int part = Utils.toPositive(nextValue) % availablePartitions.size();
return ((PartitionInfo)availablePartitions.get(part)).partition();
} else {
return Utils.toPositive(nextValue) % numPartitions;
}
} else {
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
} private int nextValue(String topic) {
AtomicInteger counter = (AtomicInteger)this.topicCounterMap.get(topic);
if(null == counter) {
counter = new AtomicInteger((new Random()).nextInt());
AtomicInteger currentCounter = (AtomicInteger)this.topicCounterMap.putIfAbsent(topic, counter);
if(currentCounter != null) {
counter = currentCounter;
}
} return counter.getAndIncrement();
} public void close() {
}
}
package cn.xiaojf.kafka.producer;

import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.serialization.StringSerializer;
import org.apache.kafka.common.utils.Utils; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger; /**
* 消息生产者
* @author xiaojf 2017/3/22 14:27
*/
public class MsgProducer extends Thread { private final KafkaProducer<String, String> producer;
private final String topic;
private final boolean isAsync; public MsgProducer(String topic, boolean isAsync) {
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.59.130:9092");//broker 集群地址
properties.put(ProducerConfig.CLIENT_ID_CONFIG, "MsgProducer");//自定义客户端id
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");//key 序列号方式
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");//value 序列号方式
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,CustomPartitioner.class.getCanonicalName());//自定义分区函数 // properties.load("properties配置文件"); this.producer = new KafkaProducer<String, String>(properties);
this.topic = topic;
this.isAsync = isAsync;
} @Override
public void run() {
int msgNo = 0; while (true) {
String msg = "Msg: " + msgNo;
String key = msgNo + "";
if (isAsync) {//异步
producer.send(new ProducerRecord<String, String>(this.topic,msg));
// producer.send(new ProducerRecord<String, String>(this.topic, key, msg));
} else {//同步
producer.send(new ProducerRecord<String, String>(this.topic, key, msg),
new MsgProducerCallback(System.currentTimeMillis(), key, msg));
}
}
} /**
* 消息发送后的回调函数
*/
class MsgProducerCallback implements Callback { private final long startTime;
private final String key;
private final String msg; public MsgProducerCallback(long startTime, String key, String msg) {
this.startTime = startTime;
this.key = key;
this.msg = msg;
} public void onCompletion(RecordMetadata recordMetadata, Exception e) {
long elapsedTime = System.currentTimeMillis() - startTime;
if (recordMetadata != null) {
System.out.println(msg + " be sended to partition no : " + recordMetadata.partition());
}
}
} public static void main(String args[]) {
new MsgProducer("my-replicated-topic",true).start();//开始发送消息
}
}

kafka 自定义分区器的更多相关文章

  1. kafka自定义序列化器

    <kafka权威指南> Customer.java public class Customer { private int customId; private String custome ...

  2. spark自定义分区器实现

    在spark中,框架默认使用的事hashPartitioner分区器进行对rdd分区,但是实际生产中,往往使用spark自带的分区器会产生数据倾斜等原因,这个时候就需要我们自定义分区,按照我们指定的字 ...

  3. MapReduce之自定义分区器Partitioner

    @ 目录 问题引出 默认Partitioner分区 自定义Partitioner步骤 Partition分区案例实操 分区总结 问题引出 要求将统计结果按照条件输出到不同文件中(分区). 比如:将统计 ...

  4. 玩转Kafka的生产者——分区器与多线程

    上篇文章学习kafka的基本安装和基础概念,本文主要是学习kafka的常用API.其中包括生产者和消费者, 多线程生产者,多线程消费者,自定义分区等,当然还包括一些避坑指南. 首发于个人网站:链接地址 ...

  5. kafka producer partitions分区器(七)

    消息在经过拦截器.序列化后,就需要确定它发往哪个分区,如果在ProducerRecord中指定了partition字段,那么就不再需要partitioner分区器进行分区了,如果没有指定,那么会根据k ...

  6. Spark源码分析之分区器的作用

    最近因为手抖,在Spark中给自己挖了一个数据倾斜的坑.为了解决这个问题,顺便研究了下Spark分区器的原理,趁着周末加班总结一下~ 先说说数据倾斜 数据倾斜是指Spark中的RDD在计算的时候,每个 ...

  7. RDD(六)——分区器

    RDD的分区器 Spark目前支持Hash分区和Range分区,用户也可以自定义分区,Hash分区为当前的默认分区,Spark中分区器直接决定了RDD中分区的个数.RDD中每条数据经过Shuffle过 ...

  8. Kafka的接口回调 +自定义分区、拦截器

    一.接口回调+自定义分区 1.接口回调:在使用消费者的send方法时添加Callback回调 producer.send(new ProducerRecord<String, String> ...

  9. 【Kafka】自定义分区策略

    自定义分区策略 思路 Command+Option+shift+N 调出查询页面,找到producer包的Partitioner接口 Partitioner下有一个DefaultPartitioner ...

随机推荐

  1. 线段树 poj 3468

    Description You have N integers, A1, A2, ... ,AN. You need to deal with two kinds of operations. One ...

  2. ThreadLocal学习笔记

    首先,ThreadLocal是Java语言提供的用于支持线程局部变量的标准实现类.很多时候,ThreadLocal与Synchronized在功能上有一定的共性,都可以用来解决多线程环境下线程安全问题 ...

  3. 三步快速解决dll冲突问题

    最近在推广应用我们的分布式服务网关(Web Api):业务组大部分对外的业务逻辑以HSF服务或者自定义扩展插件的方式,注册并发布到分布式服务网关中,统一对外提供WebApi服务.临时介绍下我们的分布式 ...

  4. Angular杂谈系列2-Angular2升级Angular4指南

    什么什么?Angualr4都发布了,之前不都才Angualr2的么?又要推翻重来,啊? 那当然不是,Angualr4只是一个版本号而已,本质上还是Angular2:以后,谷歌把新版本的Angualr称 ...

  5. ashMap源码阅读与解析

    目录结构 导入语 HashMap构造方法 put()方法解析 addEntry()方法解析 get()方法解析 remove()解析 HashMap如何进行遍历 导入语 HashMap是我们最常见也是 ...

  6. PHP array_filter() 函数

    定义和用法 array_filter() 函数用回调函数过滤数组中的元素,如果自定义过滤函数返回 true,则被操作的数组的当前值就会被包含在返回的结果数组中, 并将结果组成一个新的数组.如果原数组是 ...

  7. 给上传文件的input控件"美容"

    作为一名前端程序猿呢,在工作中经常会遇到form表单这种东西.然而表单的其他input控件样式还是很好改变的.但是,唯独input类型是file的文件上传控件可能就没那么好打扮的漂亮.刚好菜鸟我最近工 ...

  8. 分针网—IT教育: jquery选择器的用法

    jQuery选择器是jQuery库的一大特色,用这些选择器不但可以省去繁琐的JavaScript 书写方式,还可以节省时间和效率,正是有这些jQuery选择器,才让我们更容易的操作JavaScript ...

  9. Python安装mysqldb

    1.根据Python版本和自己的系统下载mysqldb http://www.codegood.com/downloads

  10. 从点击到呈现 — 详解一次HTTP请求

    一般来说,很多的参考资料上面都会说,http 是一个基于请求/响应的工作模式,然后画出一张浏览器和服务器的 b/s 结构图,再画上两个箭头,表示请求和响应,应该说这么解释是易懂的,一般也是够清楚的,但 ...