Kafka消息格式_SunnyZ-L的博客-程序员宅基地_kafka格式

技术标签: Kafka  

从0.8.x版本开始到现在的2.x版本,Kafka的消息格式也经历了 3 个版本: v0 版本、v1 版本和 v2 版本 。

v0版本

Kafka 从 0.8.x 版本开始到 0.10.x 版本之前的消息格式通常称为 v0 版本。

下图中左边的 “RECORD” 部分就是 v0 版本的消息格式,每个 RECORD ( v0 和 v1 版)必定对应一个 offset 和 message size。offset 用来标志它在 Partition 中的偏移量 ,这个 offset 是逻辑值,而非实际物理偏移值,message size 表示消息的大小,这两者在一起被称为日志头部 (LOG_OVERHEAD ) ,固定为12B 。LOG_OVERHEAD 和 RECORD 一起用来描述一条消息
与消息对应的还有消息集的概念(详细结构参考下图中的右边部分),消息集中包含一条或多条消息,消息集不仅是存储于磁盘及在网络上传输(Produce & Fetch)的基本形式,而且是 Kafka 中压缩的基本单元

  • crc32 (4B):crc32 校验值 。校验范围为 magic 至 value 之间。
  • magic (1B):消息格式版本号,此版本的 magic 值为 0。
  • attributes (1B):消息的属性。总共占 1 个字节,低 3 位表示压缩类型:0 表示 NONE、1 表示 GZIP、2 表示 SNAPPY、3 表示 LZ4 (LZ4 自 Kafka 0.9.x 引入),其余位保留。
  • key length (4B):表示消息的 key 的长度。如果为 -1,则表示没有设置 key ,即 key= null。
  • key:可选,如果没有 key 则无此字段。
  • value length (4B): 实际消息体的长度。如果为 -1,则表示消息为空。
  • value:消息体。可以为空,比如墓碑(tombstone)消息。

v0版本中一个消息的最小长度(RECORD_OVERHEAD_V0)为crc32+magic+attributes+keylength+value length=4B+1B+1B+4B+4B=14B。也就是说,v0版本中一条消息的最小长度为14B,如果小于这个值,那么这就是一条破损的消息而不被接收。

2.0.0 版本之前如果想要查看日志分段文件中的内容,使用 “ kafka-run-class.sh kafka.tools.DumpLogSegments --files 文件名 ” 的方式。

v1版本

Kafka 从 0.10.0 版本开始到 0.11.0 版本之前所使用的消息格式版本为 v1,比 v0 版本就多了一个 timestamp 字段,表示消息的时间戳。 v1 版本的消息结构如下图所示。

v1版本的 magic 字段的值为1。
v1版本的 attributes 字段中的低3位和v0版本的一样,还是表示压缩类型,而第4个位(bit)也被利用了起来:0表示 timestamp 类型为 CreateTime,而1表示 timestamp 类型为 LogAppendTime,其他位保留。timestamp类型由broker端参数log.message.timestamp.type来配置,默认值为CreateTime,即采用生产者创建消息时的时间戳。如果在创建 ProducerRecord 时没有显式指定消息的时间戳,那么 KafkaProducer 也会在发送这条消息前自动添加上。

v1 版本的消息的最小长度(RECORD_OVERHEAD_V1)要比 v0 版本的大 8 个字节,即22B。

消息压缩

Kafka实现的压缩方式是将多条消息一起进行压缩,这样可以保证较好的压缩效果。

在一般情况下,生产者发送的压缩数据在broker中也是保持压缩状态进行存储的,消费者从服务端获取的也是压缩的消息,消费者在处理消息之前才会解压消息,这样保持了端到端的压缩。

Kafka 通过 broker 端参数 compression.type (生产者客户端的 compression.type 参数优先级更高)来配置日志中使用哪种压缩方式,默认值为“producer”,表示保留生产者使用的压缩方式。这个参数还可以配置为"gzip"、"snappy"、"lz4",分别对应 GZIP、SNAPPY、LZ4 这 3 种压缩算法。如果参数 compression.type 配置为“uncompressed”,则表示不压缩。

压缩率是压缩后的大小与压缩前的对比。例如:把100MB的文件压缩后是90MB,压缩率为90/100×100%=90%,压缩率越小,压缩效果越好。

当消息压缩时是将整个消息集进行压缩作为内层消息(inner message),内层消息整体作为外层(wrapper message)的 value,其结构如下图所示。压缩后的外层消息(wrapper message)中的 key 为 null,所以下图左半部分没有画出key字段,value字段中保存的是多条压缩消息(inner message,内层消息),其中Record表示的是从 crc32 到 value 的消息格式。

当生产者创建压缩消息的时候,对内部压缩消息设置的 offset 从 0 开始为每个内部消息分配 offset,详细可以参考下图右半部分。其实每个从生产者发出的消息集中的消息offset都是从0开始的,当然这个offset不能直接存储在日志文件中,对 offset 的转换是在服务端进行的,客户端不需要做这个工作。外层消息保存了内层消息中最后一条消息的绝对位移(absolute offset),绝对位移是相对于整个分区而言的。参考下图,对于未压缩的情形,图右内层消息中最后一条的offset理应是1030,但被压缩之后就变成了5,而这个1030被赋予给了外层的 offset。

v1版本比v0版的消息多了一个timestamp字段。对于压缩的情形,外层消息的timestamp设置为:

  • 如果timestamp类型是CreateTime,那么设置的是内层消息中最大的时间戳。
  • 如果timestamp类型是LogAppendTime,那么设置的是Kafka服务器当前的时间戳。

内层消息的timestamp设置为:

  • 如果外层消息的timestamp类型是CreateTime,那么设置的是生产者创建消息时的时间戳。
  • 如果外层消息的timestamp类型是LogAppendTime,那么所有内层消息的时间戳都会被忽略。

对 attributes 字段而言,它的 timestamp 位只在外层消息中设置,内层消息中的timestamp类型一直都是CreateTime。

v2版本

Kafka 从 0.11.0 版本开始所使用的消息格式版本为 v2,这个版本的消息相比 v0 和 v1 的版本而言改动很大,同时还参考了 Protocol Buffer而引入了变长整型(Varints)和ZigZag编码。

……

2.0.0版本开始如果想要查看日志分段文件中的内容,使用 “ kafka-dump-log.sh --files 文件名 ” 的方式。

2.x版本前后两种查看日志分段的方式在本质上没有什么区别,只不过在Kafka 2.0.0之前并没有kafka-dump-log.sh脚本,所以只能使用kafka-run-class.sh kafka.tools.DumpLogSegments的形式,而从Kafka 2.0.0开始,可以直接使用kafka-dump-log.sh脚本来避免书写错误。通过查看kafka-dump-log.sh脚本可以发现,内部还是使用kafka-run-class.sh kafka.tools.DumpLogSegments的方式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33446500/article/details/105776207

智能推荐

计算机网络接口转换器,USB 3.2 Gen 1 对 5GbE 网络转换器_何静回来了的博客-程序员宅基地

为您的笔电扩充 5GbE 有线网络想象您带着无线笔电到了没有无线网络的环境,而计算机却没有实体网络孔,只好双手一摊无计可施。QNA-UC5G1T 可为您的笔电扩充高达 5GbE 高速有线网络,只需连接计算机的 USB 3.2 Gen 1 Type-A 或 Type-C (须额外选购 Type-C 对 Type-C 线材) 接口且无须额外接电,瞬间解决网络不通困扰。有了 QNA-UC5G1T,经常出...

python的发音_weixin_33795806的博客-程序员宅基地

我一直读的是:拍方(可能是受有道词典发音的影响了~),可是别人都听不懂,他们大多是读的拍森。来看看下面这个小伙伴的解释,感觉他说的挺好:“θ”这个字符的发音,有80%的中国人(学英文的人)都读错。中部地区以上的人(包括北方人)大多读成“s”,譬如:thanks->三可四thing->醒python->派森而南方人,尤其是海南、广东、广西的人大多读成“...

java文件流大小_java IO流 文件大小记载_唤吱吱的博客-程序员宅基地

publicvoidencryptFile(StringfileName){FileInputStreamfis=null;Filefile=null;try{file=newFile(fileName);fis=newFileInputStream(file);System.out.println(file.length());System.out.println(fis....

EventBus3.0框架使用详细讲解_峥嵘life的博客-程序员宅基地_eventbus和rxjava

EventBus3.0框架使用详细讲解EventBus和RxJava、RxAndroid出现的时期是差不多的,而且功效也是类似,之前有用过RxJava和RxAndroid,其实很是比较麻烦的,那些类太多了,很多名词不用就不记得了,并且学起来耗费不少时间。EventBus概述EventBus是针一款对Android的发布/订阅事件总线。它可以让我们很轻松的实现在Android各个组件之间传递消息。

hiho1393二分图多重匹配_weixin_30508241的博客-程序员宅基地

题目链接:【http://hihocoder.com/problemset/problem/1393】题意:中文题意。题解:二分图的多重匹配。主要是建图然后跑一个最带流,再判断一下就可以了。建图:首先要保证每个学生最多选择a[i]节课,那么我们建立一个超级起点S,S->学生,流量为学生最多选的课数,然后每个学生向它喜欢的课程建立一条流量为1的边,然后又要保证每个项目的人...

随便推点

PreparedStatement的使用好处_糯米q的博客-程序员宅基地_preparedstatement作用

数据库连接被用于向数据库服务器发送命令和SQL语句,在连接建立后,需要对数据库进行访问,执行sql语句在java.sql包中有3个接口分别定义了对数据库的调用的不同方式:Statement,PreparedStatement,CallableStatemen。PreparedStatement接口是Statement的子接口,它表示一条预编译过的SQL语句,有如下好处:1代码的可读性和可维护性2 PreparedStatement能提高性能:PreparedStatement执行sql后为预编译

安卓9 怎么运行老程序_这些安卓应用程序一直在后台运行,即使您关了它_weixin_39796152的博客-程序员宅基地

广告客户可能会违反Google的规定,正在收集可帮助他们摆脱Android隐私功能的信息。有些应用可能会跟踪您的活动,即使您告诉他们忘记过去。你无能为力。根据国际计算机科学研究所的研究,大约17,000个Android应用程序收集识别信息,这些信息可以在您的设备上创建活动的永久记录。研究人员说,数据收集似乎违反了搜索巨头收集数据的政策,这些数据可用于在大多数情况下针对用户进行广告宣传。这些应用可以...

L1-001 Hello World (5 分)_轻舟不载愁的博客-程序员宅基地

这道超级简单的题目没有任何输入。你只需要在一行中输出著名短句“Hello World!”就可以了。输入样例:无输出样例:Hello World!#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#inclu...

【转】mysql_fetch_row , mysql_fetch_array , mysql_fetch_assoc 的区别_weixin_34221775的博客-程序员宅基地

<?php$link = mysql_connect('localhost', 'root', ”);mysql_select_db('abc', $link);$sql = “select * from book”;$result = mysql_query($sql);while($row = mysql_fetch_row($result)){  ech...

pycharm导入talib的方法_塞班呢的博客-程序员宅基地_pycharm talib

pycharm的py文件是不认识talib的,所以不能在pycharm里面像安装numpy、pandas库那样直接安装talib所以我们要手动将我们下载好的ta-lib库导入到我们的程序中导入方法首先你得下载好ta-lib库不会的参考:Ta-Lib的下载方法(详细步骤)_a18307096730的博客-程序员宅基地然后在python/Lib/site-packages目录下找到TA_Lib-0.4.21.dist-info和ta-lib目录将这两个文件复制到我...

按位与的运算符号计算机语言,C中的按位运算符_weixin_39629989的博客-程序员宅基地

C中的按位运算符逐位运算符是用于在位级别对数据执行运算符的运算运算符。当我们执行按位运算时,这也称为位级编程。它由两位数字(0或1)组成。主要用于数值计算中,以加快计算速度。在C编程语言中,我们有不同类型的按位运算运算符。以下是按位运算运算符的列表:OperatorMeaning of operator&Bitwise AND operator|Bitwise OR operator^Bi...

推荐文章

热门文章

相关标签