Kafka

LogSegment 日志分段与稀疏索引

·4 分钟阅读·1484 字

Kafka 组件/原理详解

📋 目录

一、LogSegment 整体作用

一个 Partition 物理上被切分成多个定长日志段文件,单个segment默认上限 log.segment.bytes=1G

  • 新消息永远追加写入当前活跃segment
  • 达到大小阈值 / 写入空闲超时 log.roll.ms,关闭当前段,新建一个segment。

分区目录结构示例:

test-0/
  00000000000000000000.log       消息数据文件
  00000000000000000000.index     offset稀疏索引
  00000000000000000000.timeindex 时间戳索引
  00000000000000107435.log
  00000000000000107435.index

文件名数字 = 当前segment第一条消息的全局offset。

二、.log 消息文件

  1. 消息顺序追加写入,二进制紧凑存储,每条消息:offset+时间戳+消息长度+key+value;
  2. Kafka删除策略不会原地擦除数据,直接删除整个过期segment文件(按存储大小/保留时间),大幅降低随机IO;
  3. 日志压缩compact模式:只保留同一个key最新数据,用于配置类数据。

三、.index 稀疏偏移索引(重点)

1. 稀疏含义

不会给每条消息建索引,间隔N条消息才记录一条索引(默认索引间隔 index.interval.bytes=4KB
索引条目:(相对offset, 文件物理偏移position)

  • 相对offset:本条相对于segment起始offset的差值
  • position:消息在.log文件里的字节位置

2. 根据全局offset查找消息完整流程

  1. 利用文件名,快速定位该offset落在哪个segment;
  2. 索引二分查找:在.index找到小于目标offset最大的索引项
  3. 根据position跳到.log对应物理位置,从该位置向后顺序遍历消息,精准定位目标offset。

稀疏索引目的:索引文件体积极小,可以全部mmap进PageCache常驻内存,查询极少落地磁盘。

误区

index不存全量offset,不能一步精准定位,需要少量顺序扫描。

四、.timeindex 时间索引

条目:(相对时间戳, 对应相对offset)
根据消费时间范围查询时:

  1. timeindex二分找到时间对应的offset;
  2. 复用.index继续定位物理位置。

五、mmap与PageCache结合

  1. index、timeindex全部使用mmap内存映射加载到PageCache,进程操作索引等价操作内核缓存,无用户态拷贝;
  2. .log文件读写靠普通write/read+sendfile,依托PageCache缓存热点数据。

六、segment滚动三大触发条件

  1. 文件达到log.segment.bytes(1G)立即切新段;
  2. 距离上一次写入超过log.roll.ms空闲超时,新建segment;
  3. 主动调用日志滚动命令。

七、日志清理两种策略

  1. 基于时间删除log.retention.hours,过期整个segment删除;
  2. 基于空间删除log.retention.bytes,分区总容量超限,删最老segment;

两条任一满足即清理。


关联文档