kafka版本0.8.2.1

Java客户端版本0.9.0.0

为了更好的实现负载均衡和消息的顺序性,Kafka Producer可以通过分发策略发送给指定的Partition。Kafka保证在partition中的消息是有序的。Kafka Java客户端有默认的Partitioner。实现如下:

  1. public int partition(ProducerRecord<byte[], byte[]> record, Cluster cluster) {
  2. List partitions = cluster.partitionsForTopic(record.topic());
  3. int numPartitions = partitions.size();
  4. if(record.partition() != null) {
  5. if(record.partition().intValue() >= 0 && record.partition().intValue() < numPartitions) {
  6. return record.partition().intValue();
  7. } else {
  8. throw new IllegalArgumentException("Invalid partition given with record: " + record.partition() + " is not in the range [0..." + numPartitions + "].");
  9. }
  10. } else if(record.key() == null) {
  11. int nextValue = this.counter.getAndIncrement();
  12. List availablePartitions = cluster.availablePartitionsForTopic(record.topic());
  13. if(availablePartitions.size() > 0) {
  14. int part = Utils.abs(nextValue) % availablePartitions.size();
  15. return ((PartitionInfo)availablePartitions.get(part)).partition();
  16. } else {
  17. return Utils.abs(nextValue) % numPartitions;
  18. }
  19. } else {
  20. return Utils.abs(Utils.murmur2((byte[])record.key())) % numPartitions;
  21. }
  22. }

从源码可以看出,首先获取topic的所有Patition,如果客户端不指定Patition,也没有指定Key的话,使用自增长的数字取余数的方式实现指定的Partition。这样Kafka将平均的向Partition中生产数据。测试代码如下:

Producer:

  1. String topic = "haoxy1";
  2.  
  3. int i = 0;
  4.  
  5. Properties props = new Properties();
  6. props.put("bootstrap.servers", "10.23.22.237:9092,10.23.22.238:9092,10.23.22.239:9092");
  7. props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
  8. props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
  9.  
  10. KafkaProducer<String, String> producer = new KafkaProducer<String, String>(props);
  11.  
  12. System.out.println("partitions count " + producer.partitionsFor(topic));
  13. while(true) {
  14. String msg = "test"+i++;
  15.  
  16. ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>(topic, msg);
  17. producer.send(producerRecord);
  18. System.out.println("send " + msg);
  19. Thread.sleep(5000);
  20. }

Consumer:

  1. String topic = "haoxy1";
  2.  
  3. Properties props = new Properties();
  4. props.put("zookeeper.connect", "10.23.22.237:2181,10.23.22.238:2181,10.23.22.239:2181");
  5. props.put("group.id", "cg.nick");
  6. props.put("consumer.id", "c.nick");
  7.  
  8. Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
  9. topicCountMap.put(topic, 3);
  10. ConsumerConfig consumerConfig = new ConsumerConfig(props);
  11. ConsumerConnector consumer = Consumer.createJavaConsumerConnector(consumerConfig);
  12. Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap);
  13. List<KafkaStream<byte[], byte[]>> streams = consumerMap.get(topic);
  14. ExecutorService executor = Executors.newFixedThreadPool(3);
  15. for (final KafkaStream stream : streams) {
  16. executor.submit(new Runnable() {
  17. public void run() {
  18. ConsumerIterator<byte[], byte[]> it = stream.iterator();
  19. while (it.hasNext()) {
  20. MessageAndMetadata<byte[], byte[]> mm = it.next();
  21. System.out.println(String.format("partition = %s, offset = %d, key = %s, value = %s", mm.partition(), mm.offset(), mm.key(), new String(mm.message())));
  22. }
  23. }
  24. });
  25. }

从测试结果结果看出,是平均分配的:

  1. partition = 1, offset = 416, key = null, value = test9
  2. partition = 0, offset = 386, key = null, value = test10
  3. partition = 2, offset = 454, key = null, value = test11
  4. partition = 1, offset = 417, key = null, value = test12
  5. partition = 0, offset = 387, key = null, value = test13
  6. partition = 2, offset = 455, key = null, value = test14
  7. partition = 1, offset = 418, key = null, value = test15
  8. partition = 0, offset = 388, key = null, value = test16

如果想要控制发送的partition,则有两种方式,一种是指定partition,另一种就是根据Key自己写算法。继承Partitioner接口,实现其partition方法。并且配置启动参数

  1. props.put("partitioner.class","TestPartitioner")。

比如需要实现

key=’aaa’ 的都进partition 0

key=’bbb’ 的都进partition 1

key=’bbb’ 的都进partition 2

  1. public class TestPartitioner implements Partitioner {
  2. public int partition(String s, Object key, byte[] bytes, Object o1, byte[] bytes1, Cluster cluster) {
  3. if (key.toString().equals("aaa"))
  4. return 0;
  5. else if (key.toString().equals("bbb"))
  6. return 1;
  7. else if (key.toString().equals("ccc"))
  8. return 2;
  9. else return 0;
  10. }
  11.  
  12. public void close() {
  13.  
  14. }
  15.  
  16. public void configure(Map<String, ?> map) {
  17.  
  18. }
  19. }

测试结果:

  1. partition = 0, offset = 438, key = aaa, value = test32
  2. partition = 1, offset = 448, key = bbb, value = test33
  3. partition = 2, offset = 486, key = ccc, value = test34
  4. partition = 0, offset = 439, key = aaa, value = test35
  5. partition = 1, offset = 449, key = bbb, value = test36
  6. partition = 2, offset = 487, key = ccc, value = test37
  7. partition = 0, offset = 440, key = aaa, value = test38
  8. partition = 1, offset = 450, key = bbb, value = test39
  9. partition = 2, offset = 488, key = ccc, value = test40
  10. partition = 0, offset = 441, key = aaa, value = test41
  11. partition = 1, offset = 451, key = bbb, value = test42
  12. partition = 2, offset = 489, key = ccc, value = test43
  13. partition = 0, offset = 442, key = aaa, value = test44

如果你使用的不是Java的客户端,是javaapi下面的Producer的话,自定义的分区类需要实现kafka.producer.Partitioner,并且有构造函数。

  1. public class TestPartitioner implements Partitioner {
  2. public TestPartitioner (VerifiableProperties props) {
  3.  
  4. }
  5. public int partition(Object o, int i) {
  6. if (o.toString().equals("aaa"))
  7. return 0;
  8. else if (o.toString().equals("bbb"))
  9. return 1;
  10. else if (o.toString().equals("ccc"))
  11. return 2;
  12. else return 0;
  13. }
  14. }

Kafka学习笔记(二):Partition分发策略的更多相关文章

  1. 大数据 -- kafka学习笔记:知识点整理(部分转载)

    一 为什么需要消息系统 1.解耦 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险.许多 ...

  2. kafka学习笔记(一)消息队列和kafka入门

    概述 学习和使用kafka不知不觉已经将近5年了,觉得应该总结整理一下之前的知识更好,所以决定写一系列kafka学习笔记,在总结的基础上希望自己的知识更上一层楼.写的不对的地方请大家不吝指正,感激万分 ...

  3. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  4. muduo学习笔记(二)Reactor关键结构

    目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...

  5. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  6. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  7. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  8. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  9. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  10. 《SQL必知必会》学习笔记二)

    <SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...

随机推荐

  1. Android学习笔记01-Mac下搭建Java开发环境

    一 安装JDK 下载 mac 下专用的jdk1.7, 下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downlo ...

  2. MyEclipse------PreparedStatement使用方法

    testPreparedStatement.jsp <%@ page language="java" import="java.util.*" pageE ...

  3. day4作业之信息表

    实在是太low了,终究是自己写的,记录下 #!/usr/bin/env python # coding=utf8 import os, re #这里我把查询这块分为3个函数了,纠结了很久是放一起还是分 ...

  4. css获取实时样式

    function getStyle(elem,styleName){ if(elem.style[styleName]){//内联样式 return elem.style[styleName]; } ...

  5. Linux下修改计算机名

    SuSe操作系统: 1.  修改/etc/HOSTNAME 文件  ,其内容为计算机名. 输入命令:vi /etc/HOSTNAME 使用键盘上的 x 键一个一个删除所有内容 ,然后使用键盘上的 i ...

  6. C# Socket大文件上传

    public sealed class SocketData { private SocketData() { } public static SendFileMode SendFile(Socket ...

  7. 5个常用Java代码混淆器 助你保护你的代码

    [IT168 技术文档] 从事Java编程的人都知道,可以通过逆向工程反编译得到Java程序的源代码,这种反编译工具之一就是JAD.因此,为保护我们的劳动成果,尽可能给反编译人员制造障碍,我们可以使用 ...

  8. Oracle 11g客户端在Linux系统上的配置步骤详解

    Oracle 11g客户端在Linux系统上的配置步骤详解 2011-07-26 10:47 newhappy2008 CSDN博客 字号:T | T 本文我们主要介绍了Oracle 11g客户端在L ...

  9. 二分图最大匹配的K&#246;nig定理及其证明

     二分图最大匹配的K?nig定理及其证明 本文将是这一系列里最短的一篇,因为我只打算把K?nig定理证了,其它的废话一概没有.    以下五个问题我可能会在以后的文章里说,如果你现在很想知道的话,网上 ...

  10. sqlite 跨数据库查询

    try { $dbh = new PDO($dbrootemp, null, null); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_ ...