Kafka Offset Storage

 

1.概述

  目前,Kafka 官网最新版[0.10.1.1],已默认将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中。其实,早在 0.8.2.2 版本,已支持存入消费的 offset 到Topic中,只是那时候默认是将消费的 offset 存放在 Zookeeper 集群中。那现在,官方默认将消费的offset存储在 Kafka 的Topic中,同时,也保留了存储在 Zookeeper 的接口,通过 offsets.storage 属性来进行设置。

2.内容

  其实,官方这样推荐,也是有其道理的。之前版本,Kafka其实存在一个比较大的隐患,就是利用 Zookeeper 来存储记录每个消费者/组的消费进度。虽然,在使用过程当中,JVM帮助我们完成了自一些优化,但是消费者需要频繁的去与 Zookeeper 进行交互,而利用ZKClient的API操作Zookeeper频繁的Write其本身就是一个比较低效的Action,对于后期水平扩展也是一个比较头疼的问题。如果期间 Zookeeper 集群发生变化,那 Kafka 集群的吞吐量也跟着受影响。

  在此之后,官方其实很早就提出了迁移到 Kafka 的概念,只是,之前是一直默认存储在 Zookeeper集群中,需要手动的设置,如果,对 Kafka 的使用不是很熟悉的话,一般我们就接受了默认的存储(即:存在 ZK 中)。在新版 Kafka 以及之后的版本,Kafka 消费的offset都会默认存放在 Kafka 集群中的一个叫 __consumer_offsets 的topic中。

  当然,其实她实现的原理也让我们很熟悉,利用 Kafka 自身的 Topic,以消费的Group,Topic,以及Partition做为组合 Key。所有的消费offset都提交写入到上述的Topic中。因为这部分消息是非常重要,以至于是不能容忍丢数据的,所以消息的 acking 级别设置为了 -1,生产者等到所有的 ISR 都收到消息后才会得到 ack(数据安全性极好,当然,其速度会有所影响)。所以 Kafka 又在内存中维护了一个关于 Group,Topic 和 Partition 的三元组来维护最新的 offset 信息,消费者获取最新的offset的时候会直接从内存中获取。

3.实现

  那我们如何实现获取这部分消费的 offset,我们可以在内存中定义一个Map集合,来维护消费中所捕捉到 offset,如下所示:

  1. protected static Map<GroupTopicPartition, OffsetAndMetadata> offsetMap = new ConcurrentHashMap<>();

  然后,我们通过一个监听线程来更新内存中的Map,代码如下所示:

  1. private static synchronized void startOffsetListener(ConsumerConnector consumerConnector) {
  2. Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
  3. topicCountMap.put(consumerOffsetTopic, new Integer(1));
  4. KafkaStream<byte[], byte[]> offsetMsgStream = consumerConnector.createMessageStreams(topicCountMap).get(consumerOffsetTopic).get(0);
  5.  
  6. ConsumerIterator<byte[], byte[]> it = offsetMsgStream.iterator();
  7. while (true) {
  8. MessageAndMetadata<byte[], byte[]> offsetMsg = it.next();
  9. if (ByteBuffer.wrap(offsetMsg.key()).getShort() < 2) {
  10. try {
  11. GroupTopicPartition commitKey = readMessageKey(ByteBuffer.wrap(offsetMsg.key()));
  12. if (offsetMsg.message() == null) {
  13. continue;
  14. }
  15. OffsetAndMetadata commitValue = readMessageValue(ByteBuffer.wrap(offsetMsg.message()));
  16. offsetMap.put(commitKey, commitValue);
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }

  在拿到这部分更新后的offset数据,我们可以通过 RPC 将这部分数据共享出去,让客户端获取这部分数据并可视化。RPC 接口如下所示:

  1. namespace java org.smartloli.kafka.eagle.ipc
  2.  
  3. service KafkaOffsetServer{
  4. string query(1:string group,2:string topic,3:i32 partition),
  5. string getOffset(),
  6. string sql(1:string sql),
  7. string getConsumer(),
  8. string getActiverConsumer()
  9. }

  这里,如果我们不想写接口来操作 offset,可以通过 SQL 来操作消费的 offset 数组,使用方式如下所示:

  • 引入依赖JAR
  1. <dependency>
  2. <groupId>org.smartloli</groupId>
  3. <artifactId>jsql-client</artifactId>
  4. <version>1.0.0</version>
  5. </dependency>
  • 使用接口
  1. JSqlUtils.query(tabSchema, tableName, dataSets, sql);

  tabSchema:表结构;tableName:表名;dataSets:数据集;sql:操作的SQL语句。

4.预览

  消费者预览如下图所示:

  正在消费的关系图如下所示:

  消费详细 offset 如下所示:

  消费和生产的速率图,如下所示:

5.总结

  这里,说明一下,当 offset 存入到 Kafka 的topic中后,消费线程ID信息并没有记录,不过,我们通过阅读Kafka消费线程ID的组成规则后,可以手动生成,其消费线程ID由:Group+ConsumerLocalAddress+Timespan+UUID(8bit)+PartitionId,由于消费者在其他节点,我们暂时无法确定ConsumerLocalAddress。最后,欢迎大家使用 Kafka 集群监控 ——[ Kafka Eagle ],[ 操作手册 ]。

Kafka Offset 1的更多相关文章

  1. Kafka Offset相关命令总结

    Kafka Offset相关命令总结 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询topic的offset的范围 1>.查询某个topic的offset的最小值 [ ...

  2. kafka集群监控工具之三--kafka Offset Monitor

    1.介绍 一般情况下,功能简单的kafka项目  使用运维命令+kafka Offset Monitor 就足够用了. 2.使用2.1 部署 github下载jar包 KafkaOffsetMonit ...

  3. Kafka Offset Storage

    1.概述 目前,Kafka 官网最新版[0.10.1.1],已默认将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中.其实,早在 0.8.2. ...

  4. kafka offset 设置

    from kafka import KafkaConsumer from kafka import TopicPartition from kafka.structs import OffsetAnd ...

  5. 关于 Kafka offset

    查询topic的offset的范围 用下面命令可以查询到topic:Mytopic broker:SparkMaster:9092的offset的最小值: bin/kafka-run-class.sh ...

  6. Spark createDirectStream 维护 Kafka offset(Scala)

    createDirectStream方式需要自己维护offset,使程序可以实现中断后从中断处继续消费数据. KafkaManager.scala import kafka.common.TopicA ...

  7. kafka offset的存储问题

    注意:从kafka-0.9版本及以后,kafka的消费者组和offset信息就不存zookeeper了,而是存到broker服务器上,所以,如果你为某个消费者指定了一个消费者组名称(group.id) ...

  8. using kafkacat reset kafka offset

    1. install kafkacat Ubuntu apt-get install kafkacat CentOS install deepenency yum install librdkafka ...

  9. kafka offset存储

    存储方式 方式 方式来源 存储位置 自动提交 kafka kafka 异步提交 kafka kafka checkpoint spark streaming hdfs hbase存储 程序开发 hba ...

随机推荐

  1. 【BZOJ 3998】弦论

    [链接]h在这里写链接 [题意]     给你一个长度为n的子串;     让你求出第k小的子串是什么;     输出答案的类型分两种;     第一种,重复的算两次,第二种,重复的算一次.     ...

  2. POJ 3100 Root of the Problem || 1004 Financial Management 洪水!!!

    水两发去建模,晚饭吃跟没吃似的,吃完没感觉啊. ---------------------------分割线"水过....."--------------------------- ...

  3. 34、JZ2440上WIFI网卡使用

    :http://wireless.kernel.org在这个网站上的document中有下面说有内容的介绍 1. 准备工作(虚拟机,开发板)及配置内核选择WIFI驱动1.1 选型:确定网卡的VID,P ...

  4. jQuery实现点击开关图片切换

    原型大概是这样的 image 需求:点击右侧的蓝色眼睛,会变成 关键代码: /* 实现图片切换 */ $(".imgclick").toggle(function(){ $(thi ...

  5. win32中SetCapture 和 ReleaseCapture的使用(查一下在VCL中的使用)

    最近在用win32写<visual C++经典游戏程序设计>中的扫雷游戏,在写到鼠标点击雷区的时候用到了SetCapture,和ReleaseCapture这对系统函数. 那么为什么需要用 ...

  6. Android使用BitmapFactory.Options解决加载大图片内存溢出问题

    由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出.Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存溢出(java.lang.OutOfM ...

  7. 【MySQL】15个有用的MySQL/MariaDB性能调整和优化技巧

    MySQL 是一个强大的开源关系数据库管理系统(简称 RDBMS).它发布于 1995 年(20年前).它采用结构化查询语言(SQL),这可能是数据库内容管理中最流行的选择.最新的 MySQL 版本是 ...

  8. Struts(22)标签库具体解释

    要使用Struts2的标签,仅仅须要在JSP页面加入例如以下一行定义就可以: <%@ taglib prefix="s" uri="/struts-tags&quo ...

  9. 1.2.4 Java Annotation 提要

    (本文是介绍依赖注入容器Spring和分析JUnit源码的准备知识) Java Annotation(标注) java.lang.annotation.Annotation是全部Java标注的父接口. ...

  10. ios开发swift学习第三天:逻辑分支

    一. 分支的介绍 分支即if/switch/三目运算符等判断语句 通过分支语句可以控制程序的执行流程 二. if分支语句 和OC中if语句有一定的区别 判断句可以不加() 在Swift的判断句中必须有 ...