Kafka 数据存储与清理机制:Topic、Partition、Segment与日志删除
Kafka 的底层不是把消息一条条放进传统队列,而是把 Topic 的数据按 Partition 写成追加日志。理解它的存储结构,才能解释为什么 Kafka 能高吞吐,也能解释日志为什么可以按时间或大小清理。
一句话概括:Kafka 中 Topic 数据落在 Partition 上,每个 Partition 又被拆成多个 Segment;每个 Segment 通常包含.log数据文件、.index偏移量索引和.timeindex时间索引。分段让查找更快,也让过期日志删除更方便。
Topic、Partition、Segment 的关系
Kafka 的存储结构可以这样理解:
Topic ├── Partition 0 │ ├── Segment 0 │ │ ├── .log │ │ ├── .index │ │ └── .timeindex │ └── Segment 1 ├── Partition 1 └── Partition 2| 层级 | 作用 |
|---|---|
| Topic | 业务主题,比如订单事件、用户行为 |
| Partition | Topic 的物理分片,提高并行能力 |
| Segment | Partition 的日志分段,便于查找和清理 |
.log | 真正保存消息数据 |
.index | Offset 到物理位置的稀疏索引 |
.timeindex | 时间到 Offset 的索引 |
Partition 是 Kafka 并行能力的基础,Segment 是 Kafka 管理磁盘文件的基础。
为什么要分段
如果一个 Partition 只对应一个巨大文件,查找和删除都会很麻烦。
分段之后有两个明显好处:
| 好处 | 说明 |
|---|---|
| 查找更方便 | 先定位 Segment,再通过索引定位消息 |
| 删除更方便 | 过期数据所在的旧 Segment 可以整体删除 |
这就是为什么 Kafka 的日志清理通常可以按 Segment 粒度执行,而不是一条条消息删除。
日志清理策略一:按保留时间
课件里提到第一种清理策略是按时间。消息在 Kafka 中保存超过指定时间后,会触发清理。
默认保留时间常见是 168 小时,也就是 7 天。
这种策略适合大多数日志、行为数据、事件流水场景。业务只关心最近一段时间的数据,超过保留期就可以清理。
日志清理策略二:按存储大小
第二种策略是按 Topic 占用空间大小。当 Topic 日志文件大小超过阈值后,Kafka 会删除更旧的数据。
按大小清理通常用于控制磁盘成本。它需要结合业务可接受的数据保留范围来配置,否则可能出现数据还没来得及被下游处理就被清掉。
清理机制的工程影响
Kafka 的消息不是消费完就立刻删除。消费者只是提交自己的 Offset,消息仍然会在 Kafka 中保存到保留策略触发。
这带来两个重要影响:
| 影响 | 说明 |
|---|---|
| 可以重复消费 | 只要日志还在,可以重置 Offset 重新消费 |
| 磁盘要规划 | 高吞吐 Topic 必须估算保留时间和磁盘容量 |
如果业务需要重新补数据,比如修复一个消费程序 bug,可以把消费者组 Offset 回退到旧位置重新消费。但前提是旧日志还没被清理。
面试回答模板
可以这样答:
Kafka 的数据是按照 Topic、Partition、Segment 三级结构存储的。Topic 会拆成多个 Partition,每个 Partition 在磁盘上又会分成多个 Segment。每个 Segment 通常包含
.log数据文件、.index偏移量索引文件和.timeindex时间索引文件。分段的好处是减少单个文件大小,提高查找效率,也方便清理过期数据。Kafka 的日志清理主要有两类策略:第一是按保留时间,消息保存超过指定时间后删除,默认常见是 168 小时;第二是按 Topic 日志大小,超过阈值后删除最旧的数据。消费者提交 Offset 不代表消息立即删除,消息是否删除由日志保留策略决定。
小结
Kafka 存储结构可以记成一句话:
Partition 负责并行,Segment 负责文件管理,Retention 负责清理。
