kafka-之分段日志文件索引

0 前言

kafka的日志文件索引是用来快速检索日志的,在kafka中日志索引分为2种类,kafka中索引以稀疏索引的方式构建索引,它不保证每个消息在索引文件中都存在索引,每当写入一定数量log.index.interval.bytes default(4KB = 4096)的时候,偏移量索引以及时间戳索引各自创建一个对应的索引项,我们可以通过该参数调整索引的密度。通过MappedByteBuffer将索引文件映射到内存中。

  • 偏移量索引
  • baseoffset.index文件
  • 时间戳索引
  • baseoffset.timeindex文件

0.1 日志分段文件切分条件如下

  • 当日志分段文件的大小超过log.segment.bytes=1073741824(1GB)时;
  • 当日志分段中的最大时间戳与当前系统的差值大于log.roll.mslog.roll.hours,默认只配置了log.roll.hours =168(7天),前者优先级高
  • 偏移量索引文件或者时间戳索引文件大小超过brokerlog.index.size.max.bytes=10MB
  • 新追加消息的offset-baseOffset > Integer.MAX_VALUE时,也就是相对位移过大,用Integer-4个字节存不下了。

1 偏移量索引

偏移量索引分为2个部分,总共占8个字节

具体的偏移量索引项如下图

kafka默认拉取时间间隔 kafka timeindex_kafka

  • relativeOffset(4B)
  • 消息的相对偏移量,即offset - baseOffset,其中baseOffset为整个segmentLogFile的起始消息的offset。
  • 平常的offset占用8个Byte,而ralativeOffset只需要占用4个Byte
  • position(4B)
  • 物理地址,也就是日志在分段日志文件中的实际位置。

1.1 查看日志以及索引文件的方式

#以下2种方式都行
bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files  /cxxxxxx.log
bin/kafka-dump-log.sh --files /xxxxx.index

>>>>>>
(base) bogon:topic1-0 shufang$ kafka-dump-log.sh --files 00000000000000000000.index 
Dumping 00000000000000000000.index
offset: 45 position: 4140  #代表团一个RecordBatch
offset: 90 position: 8266  #代表另一个RecordBatch

1.2 offset索引的检索流程

假如有以下索引文件与分段日志文件,我们该如何找到偏移量为23的消息数据?

kafka默认拉取时间间隔 kafka timeindex_索引_02

  • 首先通过二分法找到不大于23的最大偏移量索引【22,656】;
  • 然后从position(656)开始顺序查找偏移量为23的消息。

注意⚠️:log.index.size.max.bytes必须是8的整数倍,如果你设置成67,那么系统会默认帮你纠正成64。

2 时间戳索引

时间戳索引分为2部分,公占12个字节,具体索引样式如下

kafka默认拉取时间间隔 kafka timeindex_偏移量_03

  • timestamp
  • 当前日志分段文件中建立索引的消息的时间戳
  • 为了保证时间戳大的单调递增,我们可以将log.message.timestamp.type设置成logApendTime,而CreateTime不能保证
  • relativeoffset
  • 时间戳对应消息的相对偏移量

2.1 具体时间戳索引的检索流程

kafka默认拉取时间间隔 kafka timeindex_时间戳_04

  • 首先在时间戳索引文件中找到不大于该时间戳的最大时间戳对应的最大索引项【1526384718283,28】;
  • 然后在偏移量索引文件中检索不超过对应relativeoffset(28)的最大偏移量索引的项【26,838】;
  • 然后按照偏移量索引的检索方式找到对应的具体消息。

注意⚠️:时间戳索引文件的大小必须为12B的倍数。