1.概述

  在 Kafka 集群中,我们可以对每个 Topic 进行一个或是多个分区,并为该 Topic 指定备份数。这部分元数据信息都是存放在 Zookeeper 上,我们可以使用 zkCli 客户端,通过 ls 和 get 命令来查看元数据信息。通过 log.dirs 属性控制消息存放路径,每个分区对应一个文件夹,文件夹命名方式为:TopicName-PartitionIndex,该文件夹下存放这该分区的所有消息和索引文件,如下图所示:

2.内容

  Kafka 集群在生产消息入库的时候,通过 Key 来进行分区存储,按照相应的算法,生产分区规则,让所生产的消息按照该规则分布到不同的分区中,以达到水平扩展和负载均衡。而我们在消费这些消息的时候,可以使用多线程来消费该 Topic 下的所有分区中的消息。

  分区规则的制定,通过实现 kafka.producer.Partitioner 接口,该接口我们可以进行重写,按照自己的方式去实现分区规则。如下,我们按照 Key 的 Hash 值,然后取模得到分区索引,代码如下所示:

package cn.hadoop.hdfs.kafka.partition;

import kafka.producer.Partitioner;
import kafka.utils.VerifiableProperties; /**
* @Date Nov 3, 2016
*
* @Author dengjie
*
* @Note 先 Hash 再取模,得到分区索引
*/
public class CustomerPartitioner implements Partitioner { public CustomerPartitioner(VerifiableProperties props) {
} public int partition(Object key, int numPartitions) {
int partition = 0;
String k = (String) key;
partition = Math.abs(k.hashCode()) % numPartitions;
return partition;
} }

  在创建 Topic 的时候,若按照上述规则创建分区,分区数最后为 Brokers 的整数倍,这样才能发挥其负载均衡的作用,比如:当前我们集群节点由 3 个 Broker 组成,如下图所示:

2.1 创建分区

  我们在创建分区的时候,可以通过 Kafka 提供的客户端命令进行创建,如下,我们创建一个6分区,3备份的一个 Topic,命令如下所示:

./kafka-topics.sh --create --zookeeper k1:,k2:,k3: --replication-factor  --partitions  --topic ke_test

  这里需要注意的是,指定备份数的时候,备份数要小于等于 Brokers 数。否则创建失败。在创建分区的时候,假设,我们只创建 2 个分区,而我们上述图中, Brokers 有 3 个,会造成有一个 Broker 上没有该 Topic 的分区,以致分布不均。

2.2 分区入库

  一般,我们在入库消息的时候,都有使用 Kafka 的 API,如下,我们使用生产 API ,按照上述的 Hash 取模规则,进行分区入库,代码如下所示:

package cn.hadoop.hdfs.kafka.partition;

import java.util.List;
import java.util.Properties; import cn.hadoop.hdfs.kafka.partition.data.FileRead;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig; /**
* @Date Nov 3, 2016
*
* @Author dengjie
*
* @Note 按照先 Hash 再取模的规则,进行分区入库
*/
public class PartitionerProducer {
public static void main(String[] args) {
producerData();
} private static void producerData() {
Properties props = new Properties();
props.put("serializer.class", "kafka.serializer.StringEncoder");
props.put("metadata.broker.list", "k1:9092,k2:9092,k3:9092");
props.put("partitioner.class", "cn.hadoop.hdfs.kafka.partition.CustomerPartitioner");
Producer<String, String> producer = new Producer<String, String>(new ProducerConfig(props));
String topic = "ke_test";
List<String> list = FileRead.readData();
for (int i = 0; i < list.size(); i++) {
String k = "key" + i;
String v = new String(list.get(i));
producer.send(new KeyedMessage<String, String>(topic, k, v));
if (i == (list.size() - 1)) {
return;
}
}
producer.close();
}
}

  这里,我们分析发现,生产者在生产消息入库时,会按照 CustomerPartitioner 的规则,进行分区入库,在入库时,将 Key 先做 Hash,然后分区数取模(这里分区数是 6).我们计算可以得到一下信息:

hashCode("key0") %  =
hashCode("key1") % =
hashCode("key2") % =
hashCode("key3") % =
hashCode("key4") % =
hashCode("key5") % =
// ... 以此循环

  按照该表述规则进行分区入库。

2.3 分区入库验证

  接下里,我们通过 Kafka 的消费者 API 来验证,在消费时,消费 Topic 各分区的详情,代码如下所示:

package cn.hadoop.hdfs.kafka.partition;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties; import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import kafka.message.MessageAndMetadata; /**
* @Date Nov 3, 2016
*
* @Author dengjie
*
* @Note 通过 Kafka 的消费者 API 验证分区入库的消息
*/
public class PartitionerConsumer {
public static void main(String[] args) {
String topic = "ke_test";
ConsumerConnector consumer = Consumer.createJavaConsumerConnector(createConsumerConfig());
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(topic, new Integer());
Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap);
KafkaStream<byte[], byte[]> stream = consumerMap.get(topic).get();
ConsumerIterator<byte[], byte[]> it = stream.iterator();
while (it.hasNext()) {
MessageAndMetadata<byte[], byte[]> mam = it.next();
System.out.println("consume: Partition [" + mam.partition() + "] Message: [" + new String(mam.message())
+ "] ..");
} } private static ConsumerConfig createConsumerConfig() {
Properties props = new Properties();
props.put("group.id", "group1");
props.put("zookeeper.connect", "zk1:2181,zk2:2181,zk3:2181");
props.put("zookeeper.session.timeout.ms", "");
props.put("zookeeper.sync.time.ms", "");
props.put("auto.commit.interval.ms", "");
props.put("auto.offset.reset", "smallest");
return new ConsumerConfig(props);
}
}

  这里笔者只是验证消费数据,若在实际生产线上,需将上述单线程消费改造成多线程消费,来提升处理消息的能力。

2.4 验证结果

  这里,我们线运行生产者,让其生产消息,并分区入库;然后,在启动消费者,消费消息验证其结果,如下图所示:

3.总结

  需要注意的是,分区数建议为 Brokers 的整数倍,让其达到均匀分布;备份数必须小于等于 Brokers。以及,多线程消费的控制,其线程数建议和分区数相等。

4.结束语

  这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

Kafka 分区备份实战的更多相关文章

  1. [转帖]Kafka 原理和实战

    Kafka 原理和实战 https://segmentfault.com/a/1190000020120043 两个小时读完... 实在是看不完... 1.2k 次阅读  ·  读完需要 101 分钟 ...

  2. Zookeeper+Kafka完全分布式实战部署

    Zookeeper+Kafka完全分布式实战部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实我之前部署过kafak和zookeeper的完全分布式,集群是可以正常使用没错, ...

  3. 图解 Kafka 水印备份机制

    高可用是很多分布式系统中必备的特征之一,Kafka 日志的高可用是通过基于 leader-follower 的多副本同步实现的,每个分区下有多个副本,其中只有一个是 leader 副本,提供发送和消费 ...

  4. 详细解析kafka之kafka分区和副本

    本篇主要介绍kafka的分区和副本,因为这两者是有些关联的,所以就放在一起来讲了,后面顺便会给出一些对应的配置以及具体的实现代码,以供参考~ 1.kafka分区机制 分区机制是kafka实现高吞吐的秘 ...

  5. Kafka之 API实战

    Kafka之 API实战 一.环境准备 1)启动zk和kafka集群,在kafka集群中打开一个消费者 [hadoop1 kafka]$ bin/kafka-console-consumer.sh \ ...

  6. SQL Server 批量主分区备份(Multiple Jobs)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...

  7. SQL Server 批量主分区备份(One Job)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 实现代码(SQL Codes) 主分区完整.差异还原(Primary B ...

  8. kafka分区及副本在broker的分配

    kafka分区及副本在broker的分配 部分内容參考自:http://blog.csdn.net/lizhitao/article/details/41778193 以下以一个Kafka集群中4个B ...

  9. kafka分区选主机制

    Kafka Partition Leader选主机制 https://blog.csdn.net/qq_27384769/article/details/80115392 kafka leader选举 ...

随机推荐

  1. sublime Text3 插件编写教程_第一课

    今天给大家分享一下编写一个Sublime Text3 插件的流程以及使用插件解决的一个实际问题. 一.开发插件的前提条件 开发sublime插件用到的是Python语言,因此必须懂Python语言的基 ...

  2. 意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提交的javascript代码! 不敢藏私,特与大家分

    最近研发BDC 云开发部署平台的数据路由及服务管理器意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提 ...

  3. 用c#开发微信 (18) 多客服

    微信官方的多客服接口原理是通过用户发送的信息,开发者服务器返回一条指定类型的响应信息,使用户的对话状态切换到官方的多客服状态(持续一段时间),这段时间内用户发送的所有信息都不会到达开发者的服务器,而是 ...

  4. WinDbg 命令三部曲:(三)WinDbg SOSEX 扩展命令手册

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部曲:(一)WinDbg 命令手册> <WinDb ...

  5. Silverlight动态载入调用XAML资源

      以多语言为例子: ResourceDictionary resourceDictionary = new ResourceDictionary(); //新建资源集合 var culture = ...

  6. Entity Framework 乐观并发控制

    一.背景 我们知道,为了防止并发而出现脏读脏写的情况,可以使用Lock语句关键字,这属于悲观并发控制的一种技术,,但在分布式站点下,锁的作用几乎不存在,因为虽然锁住了A服务器的实例对象,但B服务器上的 ...

  7. adblockTester通过js检测用户浏览器是否安装了AdBlock

    adblockTester 简介 首先有必要介绍一下AdBlock,它是一款知名网页广告屏蔽插件,在各大主流浏览器上均有AdBlock插件. AdBlock为用户带来了一片蓝天,却苦了站长,尤其是苦逼 ...

  8. 选择哪种方式进行SharePoint的备份

    关于SharePoint的备份还原功能,大家可能都有所了解.但是SharePoint一共有多少种备份方式呢,哪种备份方式是更适合你的呢,本文主要为大家梳理,并且深入的研究一下常见的几种备份方式,以便大 ...

  9. 北大青鸟进入ASP.NET MVC的世界(一)

    今天我们开始ASP.NET  MVC 4.0课程的学习第一讲.我们今天主要关注如下5个问题: 1.理解ASP.NET MVC程序的执行过程 2.会使用ASP.NET中的系统对象 3.会搭建ASP.NE ...

  10. atitit. java queue 队列体系and自定义基于数据库的队列总结o7t

    atitit. java queue 队列体系and自定义基于数据库的队列总结o7t 1. 阻塞队列和非阻塞队列 1 2. java.util.Queue接口, 1 3. ConcurrentLink ...