一、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 消息文件
- 消息顺序追加写入,二进制紧凑存储,每条消息:offset+时间戳+消息长度+key+value;
- Kafka删除策略不会原地擦除数据,直接删除整个过期segment文件(按存储大小/保留时间),大幅降低随机IO;
- 日志压缩compact模式:只保留同一个key最新数据,用于配置类数据。
三、.index 稀疏偏移索引(重点)
1. 稀疏含义
不会给每条消息建索引,间隔N条消息才记录一条索引(默认索引间隔 index.interval.bytes=4KB)
索引条目:(相对offset, 文件物理偏移position)
- 相对offset:本条相对于segment起始offset的差值
- position:消息在.log文件里的字节位置
2. 根据全局offset查找消息完整流程
- 利用文件名,快速定位该offset落在哪个segment;
- 索引二分查找:在.index找到小于目标offset最大的索引项;
- 根据position跳到.log对应物理位置,从该位置向后顺序遍历消息,精准定位目标offset。
稀疏索引目的:索引文件体积极小,可以全部mmap进PageCache常驻内存,查询极少落地磁盘。
误区
index不存全量offset,不能一步精准定位,需要少量顺序扫描。
四、.timeindex 时间索引
条目:(相对时间戳, 对应相对offset)
根据消费时间范围查询时:
- timeindex二分找到时间对应的offset;
- 复用.index继续定位物理位置。
五、mmap与PageCache结合
- index、timeindex全部使用
mmap内存映射加载到PageCache,进程操作索引等价操作内核缓存,无用户态拷贝; - .log文件读写靠普通write/read+sendfile,依托PageCache缓存热点数据。
六、segment滚动三大触发条件
- 文件达到
log.segment.bytes(1G)立即切新段; - 距离上一次写入超过
log.roll.ms空闲超时,新建segment; - 主动调用日志滚动命令。
七、日志清理两种策略
- 基于时间删除:
log.retention.hours,过期整个segment删除; - 基于空间删除:
log.retention.bytes,分区总容量超限,删最老segment;
两条任一满足即清理。
关联文档
- Kafka 零拷贝 sendfile 完整原理 — 零拷贝与日志段
- Kafka 底层原理详解 — 日志存储架构