Kafka消息(存储)格式及索引组织方式
要深入学习Kafka,理解Kafka的存储机制是非常重要的。本文介绍Kafka存储消息的格式以及数据文件和索引组织方式,以便更好的理解Kafka是如何工作的。
Kafka消息存储格式
Kafka为了保证消息的可靠性,服务端会将接收的消息进行序列化并保存到磁盘上(Kafka的多副本存储机制),这里涉及到消息的存储格式,即消息编码后落到磁盘文件上的二进制的数据格式。下图是根据Kafka 3.0官方文档整理的消息格式:
包含三个部分:BatchRecords、Record,以及Header的编码格式。
BatchRecords是Kafka数据的存储单元,一个BatchRecords中包含多个Record(即我们通常说的一条消息)。BatchRecords中各个字段的含义如下:
字段名 | 含义 |
baseOffset | 这批消息的起始Offset |
partitionLeaderEpoch | 用于Partition的Recover时保护数据的一致性,具体场景可以见KIP101 |
batchLength | BatchRecords的长度 |
magic | 魔数字段,可以用于拓展存储一些信息,当前3.0版本的magic是2 |
crc | crc校验码,包含从attributes开始到BatchRecords结束的数据的校验码 |
attributes | int16,其中bit0~2中包含了使用的压缩算法,bit3是timestampType,bit4表示是否失误,bit5表示是否是控制指令,bit6~15暂未使用 |
lastOffsetDelta | BatchRecords中最后一个Offset,是相对baseOffset的值 |
firstTimestamp | BatchRecords中最小的timestamp |
maxTimestamp | BatchRecords中最大的timestamp |
producerId | 发送端的唯一ID,用于做消息的幂等处理 |
producerEpoch | 发送端的Epoch,用于做消息的幂等处理 |
baseSequence | BatchRecords的序列号,用于做消息的幂等处理 |
records | 具体的消息内容 |
一个BatchRecords中可以包含多条消息,即上图中的Record,而每条消息又可以包含多个Header信息,Header是Key-Value形式的。Record和Header的格式都非常简单,就不对其中的字段做解释了。
Log Segment
在Kafka中,一个Topic会被分割成多个Partition,而Partition由多个更小的,称作Segment的元素组成。
Kafka一个Partition下会包含类似上图中的一些文件,由log、index、timeindex三个文件组成一个Segment,而文件名中的(0和35)表示的是一个Segment的起始Offset(Kafka会根据log.segment.bytes的配置来决定单个Segment文件(log)的大小,当写入数据达到这个大小时就会创建新的Segment)。log、index、timeindex中存储的都是二进制的数据(log中存储的就是上一部分介绍的BatchRecords的内容,而index和timeindex分别是一些索引信息。)
下图是log文件中数据解析后的示意图(也就是本文第一部分BatchRecords格式)。其中16开头的这一行表示一个第一条消息的Offset是16的BatchRecord,而24开头的这一行表示的是一个第一条消息的Offset是24的BatchRecord。
索引
我们知道Kafka中每个Consumer消费一个Partition都会有一个关联的Offset表示已经处理过的消息的位置。通常Consumer会根据Offset连续的处理消息。而通过Offset从存储层中获取消息大致分为两步:
第一步,根据Offset找到所属的Segment文件
第二步,从Segment中获取对应Offset的消息数据
其中第一步可以直接根据Segment的文件名进行查找(上面已经介绍了Segment的文件面就是它包含的数据的起始Offset)。第二步则需要一些索引信息来快速定位目标数据在Segment中的位置,否则就要读取整个Segment文件了,这里需要的索引信息就是上面的index文件存储的内容。
index文件中存储的是Offset和Position(Offset对应的消息在log文件中的偏移量)的对应关系,这样当有Offset时可以快速定位到Position读取BatchRecord,然后再从BatchRecord中获取某一条消息。比如上述Offset25会被定位到24这个BatchRecord,然后再从这个BatchRecord中取出第二个Record(24这个BatchRecord包含了24、25两个Record)。
注意,Kafka并不会为每个Record都保存一个索引,而是根据log.index.interval.bytes等配置构建稀疏的索引信息。
除了index索引文件保存Offset和Position的映射关系外,Kafka中还维护了timeindex,保存了Timestamp和Offset的关系,用于应对一些场景需要根据timestamp来定位消息。timeindex中的一个(timestampX,offsetY)元素的含义是所有创建时间大于timestampX的消息的Offset都大于offsetY。
同样的,timeindex也采用了稀疏索引的机制,使用和index相同的配置(log.index.interval.bytes),所以timeindex和index是一一对应的。
总结
本文首先介绍了Kafka消息的存储格式,然后介绍了Kafka是如何索引(index & timeindex)存储的数据的。看完索引部分后遗留了一个疑问:每次读取消息都要先根据索引读取Position信息,然后再根据Position去读数据,而索引又是稀疏索引(查找索引也是要开销的),这样效率是否会比较低呢?如果利用Consumer总是顺序读取消息的特性,每次读取数据时都带上一些上下文信息(比如上一次Offset对应的Position信息)直接去读Log数据效率是否会更高?欢迎留言交流!
Kafka消息(存储)格式及索引组织方式的更多相关文章
- Kafka消息系统基础知识索引
一些观念的修正 从 0.9 版本开始,Kafka 的标语已经从“一个高吞吐量,分布式的消息系统”改为"一个分布式流平台". Kafka不仅仅是一个队列,而且是一个存储,有超强的堆积 ...
- Kafka(3)--kafka消息的存储及Partition副本原理
消息的存储原理: 消息的文件存储机制: 前面我们知道了一个 topic 的多个 partition 在物理磁盘上的保存路径,那么我们再来分析日志的存储方式.通过 [root@localhost ~]# ...
- Kafka消息文件存储
在对消息进行存储和缓存时,Kafka依赖于文件系统.(Page Cache) 线性读取和写入是所有使用模式中最具可预计性的一种方式,因而操作系统采用预读(read-ahead)和后写(write-be ...
- 一文看懂Kafka消息格式的演变
摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在不断的升级改进,从0.8.x版本开始到现在的1.1.x版本,Kaf ...
- 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变
转载来自朱小厮博客的 一文看懂Kafka消息格式的演变 ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...
- Kafka分片存储、消息分发和持久化机制
Kafka 分片存储机制 Broker:消息中间件处理结点,一个 Kafka 节点就是一个 broker,多个 broker 可以组成一个 Kafka集群. Topic:一类消息,例如 page vi ...
- MyISAM的前缀压缩索引在索引块中的组织方式
纯粹自己的理解,哪位大佬看到了还请指正. 首先贴一张<高性能MySQL>中的一段话: 这句话的意思是说,MyISAM使用b+树组织索引.也就是说无论索引压缩与否,组织方式一定是B+树. 下 ...
- 联合索引在B+树上的存储结构及数据查找方式
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 引言 上一篇文章<MySQL索引那些事>主要讲了MySQL索引的底层原理,且对比了B ...
- Kafka日志存储原理
引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的.每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建 ...
随机推荐
- Django——Ajax发送请求验证用户名是否被注册
场景: 用户注册的时候,输入用户名之后,Ajax发送请求到后端,后端验证该用户名是否已经被注册,然后返回到注册页面提示用户. 1.模型: from django.db import models cl ...
- 将rgb表示方式转换为hex表示方式-------------将hex表示方式转换为rgb表示方式(这里返回rgb数组组合)
/** * kevin 2021.1.4 * 将rgb表示方式转换为hex表示方式 * @param {string} rgbColor 传过来的hex格式的颜色 * @returns { ...
- 判断IE浏览器版本
//判断IE浏览器版本 function IEVersion() { var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 var isI ...
- mysql中通过sql语句查询指定数据表的字段信息
mysql数据库在安装完成时,自动创建了information_schema.mysql.test这三个数据库.其中,information_schema记录了创建的所有数据库的相关信息,因此可以 ...
- find命令查找某一个时间点以后创建或者修改的文件
touch -t 201711211615.47 starttouch -t 201711211617.47 end find ./* -newer start |xargs ls -al-rw-r- ...
- springboot 事务创建流程源码分析
springboot 事务创建流程源码分析 目录 springboot 事务创建流程源码分析 1. 自动加载配置 2. InfrastructureAdvisorAutoProxyCreator类 3 ...
- python中安装第三方库(使用豆瓣的镜像网站快速安装)
#安装第三方库#标准库,第三方库#pip install selenium 直接从官网进行安装,有时网速会有点慢#可以去国内的镜像站安装#pip install selenium -i https:/ ...
- Spring系列-SpringBase+IOC
Spring 一.前言 Thinking is more important than learning 本文主要讲述spring 以及它的 IOC原理 代码地址:https://gitee.com/ ...
- 中心对称数 II
中心对称数 II 1.题目描述 中心对称数是指一个数字在旋转了 180 度之后看起来依旧相同的数字(或者上下颠倒地看). 找到所有长度为 n 的中心对称数. 示例 : 输入: n = 2 输出: [& ...
- Docker安装flink及避坑指南
Docker安装flink 导航 无处不在的大数据 安装flink 拉取flink镜像 编写docker-compose.yml 生成启动 查看安装效果 常见坑及解决方案 问题1 问题2 参考 本 ...