kafka的存储机制
-
https://segmentfault.com/a/1190000021824942
-
https://www.lin2j.tech/md/middleware/kafka/Kafka%E7%B3%BB%E5%88%97%E4%B8%83%E5%AD%98%E5%82%A8%E6%9C%BA%E5%88%B6.html
-
https://tech.meituan.com/2015/01/13/kafka-fs-design-theory.html
-
https://feizichen.me/2019/12/KafkaFileMessage/
-
https://juejin.cn/post/6965401216599736351
存储文件结构
topic
: 可以理解为一个消息队列的名字partition
:为了实现扩展性,一个非常大的topic可以分布到多个 broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列segment
:partition物理上由多个segment组成message
:每个segment文件中实际存储的每一条数据就是messageoffset
:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中,partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息
Partition分区
假设topic
名称为test-topic
,默认设置partition
为3
,topic
创建成功后默认的存储位置在:/tmp/kafka-logs
下,分区分别以topic名称-分区数命名
,(不考虑副本的情况)如下:
//分布在不同的broker节点上
test-topic-0
test-topic-1
test-topic-2
疑问一:为什么要分区呢?
疑问二:分区文件下到底存了那些东西?
test-topic-0
├── 00000000000000000001.index
├── 00000000000000000001.log
├── 00000000000000000001.timeindex
├── 00000000000000001018.index
├── 00000000000000001018.log
├── 00000000000000001018.timeindex
├── 00000000000000002042.index
├── 00000000000000002042.log
├── 00000000000000002042.timeindex
Segment File
组成:由2大部分组成,分别为.log
和.index
文件,此 2 个文件一一对应,成对出现。Segment File
命名规则:Partion
全局的第一个Segment 从0
开始,后续每个Segment
文件名为上一个Segment
文件最后一条消息的offset
值。
index
文件为 log
文件的消息提供了索引,具体是提供某条消息所在的位置。
疑问三: 为什么有了partition还需要segment ?
Segment存储
Segment中核心文件是index索引文件和log数据文件,既然是索引文件当然是为了更高效的定位到数据,那么索引文件和数据文件中到底是存了那些数据?又是如何快速找到消息数据呢?
使用kafka自带脚本发送测试数据
sh kafka-producer-perf-test.sh --topic test-topic --num-records 50000000 --record-size 1000 --throughput 10000000 --producer-props bootstrap.servers=192.168.60.201:9092
使用kafka自带脚本Dump index
sh kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/test-topic-0/00000000000000001018.index --print-data-log
offset: 1049 position: 16205
offset: 1065 position: 32410
offset: 1081 position: 48615
offset: 1097 position: 64820
offset: 1113 position: 81025
offset: 1129 position: 97230
通过dump index
我们发现其实索引文件中其实就保存了offset
和position
,分别是消息的offset
也就是具体那一条消息,position
表示具体消息存储在log
中的物理地址。
疑问一:通过上面数据可以看出,kafka
并不是每个offset
都保存了,为什么在index
文件中这些offset
编号不是连续的呢?
使用kafka自带脚本Dump log
sh kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/test-topic-0/00000000000000001018.log --print-data-log
log
数据文件中并不是直接存储数据,而是通过许多的message
组成,message
包含了实际的消息数据。
Message字段
kafka从0.11.0版本开始所使用的消息格式版本为v2,参考了Protocol Buffer而引入了变长整型(Varints)和ZigZag编码。 Varints是使用一个或多个字节来序列化整数的一种方法,数值越小,其所占用的字节数就越少。ZigZag编码以一种锯齿形(zig-zags)的方式来回穿梭于正负整数之间, 以使得带符号整数映射为无符号整数,这样可以使得绝对值较小的负数仍然享有较小的Varints编码值,比如-1编码为1,1编码为2,-2编码为3。
未完待续。。。