消息的物理结构
就是每一条消息在log中都存了啥
关键字 | 解释说明 |
---|---|
8 byte offset | 在parition(分区)内的每条消息都有一个有序的id号,这个id号被称为偏移(offset),它可以唯一确定每条消息在parition(分区)内的位置。即offset表示partiion的第多少message |
4 byte message size | message大小 |
4 byte CRC32 | 用crc32校验message |
1 byte “magic" | 表示本次发布Kafka服务程序协议版本号 |
1 byte “attributes" | 表示为独立版本、或标识压缩类型、或编码类型。 |
4 byte key length | 表示key的长度,当key为-1时,K byte key字段不填 |
K byte key | 可选 |
value bytes payload | 表示实际消息数据。 |
offset: 3 position: 211 CreateTime: 1606446771205 isvalid: true keysize: -1 valuesize: 7 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKey s: [] payload: 4567890
基本概念
1 在kafka中,topic是一个逻辑概念
2 每一个topic的所有message 是依据partition进行物理存储的
3 partition对应的实体为目录,命名topicName-序列,序列从0开始
举个例子,有个叫做pet的topic,3个分区,则其目录结构如下
drwxr-xr-x 2 root root 215 12月 1 10:27 pet-0
drwxr-xr-x 2 root root 215 12月 1 09:51 pet-1
drwxr-xr-x 2 root root 215 12月 1 09:51 pet-2
4分区内数据按segment进行存储,(1个分区内可以有N个segment)
比如我们进入上面的pet-0分区,结果如下
-rw-r--r-- 1 root root 10485760 12月 1 09:44 00000000000000000000.index
-rw-r--r-- 1 root root 4851 12月 1 17:29 00000000000000000000.log
-rw-r--r-- 1 root root 10485756 12月 1 09:44 00000000000000000000.timeindex
-rw-r--r-- 1 root root 34 12月 1 09:44 00000000000000000000.txnindex
-rw-r--r-- 1 root root 240 12月 1 09:44 00000000000000000054.snapshot
-rw-r--r-- 1 root root 28 12月 1 10:27 leader-epoch-checkpoint
5 segment对应2个文件,xxxx.log 与xxxx.index
- .index文件存储kv堆,稀疏存储. k为log文件中的第几条消息的几, value是这个消息针对于这个文件的偏移量.
- .log文件存储的是真正的消息, log最大1G,多了会分裂
查看这个index,还是不容易的!
[root@mypc01 pet-0]# kafka-run-class.sh kafka.tools.DumpLogSegments --files /usr/local/kafka /data/kafka-logs/pet-0/00000000000000000000.index --print-data-log
Dumping /usr/local/kafka/data/kafka-logs/pet-0/00000000000000000000.index
offset: 0 position: 0
[root@mypc01 pet-0]# kafka-run-class.sh kafka.tools.DumpLogSegments --files /usr/local/kafka /data/kafka-logs/pet-0/00000000000000000000.log --print-data-log
Dumping /usr/local/kafka/data/kafka-logs/pet-0/00000000000000000000.log
Starting offset: 0
offset: 0 position: 0 CreateTime: 1606445146516 isvalid: true keysize: -1 valuesize: 0 magic: 2 co mpresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKeys: [] payload:
offset: 1 position: 68 CreateTime: 1606445348572 isvalid: true keysize: -1 valuesize: 5 magic: 2 c ompresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKeys : [] payload: gaoyu
offset: 2 position: 141 CreateTime: 1606445368962 isvalid: true keysize: -1 valuesize: 2 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKey s: [] payload: 66
offset: 3 position: 211 CreateTime: 1606446771205 isvalid: true keysize: -1 valuesize: 7 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKey s: [] payload: 4567890
offset: 4 position: 286 CreateTime: 1606448835680 isvalid: true keysize: -1 valuesize: 2 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKey s: [] payload: 10
消费者如何查找信息?
1 依据offset的值,查找index索引文件.因为index文件的命名是以上一个文件的最后一个offset命名的,所以,利用二分法可以很快找到索引文件
2 找到索引文件后,依据offset找到匹配范围的position
3 拿到position后,再到对应的log文件中,从position处开始找offset对应的消息,将每条消息的offset与目标offset进行比较,直到找到消息.
log过大的怎么办?
有大小和时间限制;
有大小限制,超过1G就会创建新文件.
有时间限制,如果保留策略设置为2天,一条记录发布后两天内,可以随时被消费,两天过后这条记录会被抛弃并释放磁盘空间。Kafka的性能和数据大小无关,所以长时间存储数据没有什么问题.
log文件和index文件的offset有何不同?
index文件中offset是稀疏存储的,log文件中不是这样的
log文件和index文件如何命名的?
log文件换index文件一一对应
而log文件的命名以其第一条记录的offset值为准
图解
总结
- kafka消息存储在分区目录下的log文件中,索引存在分区下面的索引文件中
- 消费者依据offset找到索引文件然后再去依据offset找到position,再利用position取log文件查找消息