一、Kafka 为什么需要删除策略?
Kafka 的消息存储模型:
Topic
└── Partition
└── Log Segment (日志段文件)
├── 000000000000.log
├── 000000001000.log
└── ...
关键设计:
✅ 消费不会删除数据
✅ Broker 只追加写(Append-only)
✅ 数据删除由 Broker 后台线程统一执行
因此:
Kafka 数据生命周期 = Retention Policy 决定
二、Kafka 数据删除的 3 种策略(核心)
Kafka 实际只有 两大类清理机制 + 一种组合模式:
| 策略 | 类型 | 是否默认 | 用途 |
|---|---|---|---|
| 时间删除 | delete | ✅ 默认 | 日志型系统 |
| 空间删除 | delete | ✅ 默认 | 防止磁盘爆满 |
| Log Compaction | compact | ❌ | KV/状态流 |
配置入口:
log.cleanup.policy
三、策略一:基于时间删除(Time-based Retention)
⭐ 最常用策略
原理
Kafka 定期检查:
当前时间 - Segment 最后修改时间 > retention.ms
满足条件 → 整个 Segment 删除。
⚠️ 注意:
Kafka 删除的是 Segment 文件,不是单条消息。
关键参数
1️⃣ retention.ms(核心)
log.retention.ms=604800000
默认:
7 天
含义:
数据最多保留多久
2️⃣ retention.hours(旧参数)
等价:
log.retention.hours=168
优先级:
ms > minutes > hours
删除流程
Producer 写入
↓
Segment 关闭(滚动)
↓
达到 retention.ms
↓
Log Cleaner 标记删除
↓
文件删除
重要理解(很多人误解)
Kafka 不会:
❌ 精确到消息删除
而是:
✅ 删除整个 segment
所以:
实际保留时间 ≈ retention + segment 时间
四、策略二:基于空间删除(Size-based Retention)
防止磁盘被写爆。
参数
log.retention.bytes
log.retention.bytes=10737418240
表示:
每个 partition 最大 10GB
删除逻辑
当:
Partition Size > retention.bytes
Kafka:
删除最旧 segment
直到满足限制。
注意
这是 Partition 级别,不是 Topic。
例如:
Topic 有 6 个 partition
每个 retention.bytes=10GB
总可能占用 = 60GB
五、策略三:Log Compaction(日志压缩)
这是 Kafka 最强大的特性之一。
启用方式
log.cleanup.policy=compact
或:
kafka-topics.sh --alter \
--topic user-state \
--config cleanup.policy=compact
原理(Key-Based 保留)
Kafka 保证:
每个 Key 只保留最新 Value
示例:
| Offset | Key | Value |
|---|---|---|
| 1 | A | 1 |
| 2 | B | 2 |
| 3 | A | 3 |
压缩后:
A → 3
B → 2
旧值被清理。
应用场景
非常重要:
| 场景 | 是否适合 |
|---|---|
| 用户状态 | ✅ |
| 配置中心 | ✅ |
| CDC | ✅ |
| Event Log | ❌ |
Tombstone(删除标记)
删除 Key:
key=A value=null
Kafka:
写入 tombstone
→ compaction 后彻底删除
六、delete + compact(组合模式 ⭐)
Kafka 支持:
cleanup.policy=compact,delete
效果:
先保证 Key 最新
再按时间删除旧数据
常见于:
Kafka Streams state topic
七、Segment 滚动(决定删除粒度)
删除依赖 Segment。
参数:
log.segment.bytes
默认:
1GB
或:
log.segment.ms
达到任一条件:
创建新 segment
为什么重要?
假设:
retention = 1 hour
segment.ms = 24 hours
结果:
👉 数据可能保存 24 小时!
因为 segment 未关闭。
✅ 生产建议:
segment.ms <= retention.ms / 2
八、Kafka 删除执行线程(后台机制)
负责组件:
LogManager
└── LogCleaner
周期:
log.retention.check.interval.ms
默认:
5 分钟检查一次
流程:
扫描 partition
↓
判断过期
↓
标记删除
↓
异步删除文件
九、消费者与删除策略的关系(关键)
很多人误解:
消费完是否删除?
答案:
❌ 无关
Kafka:
Consumer Offset ≠ 数据生命周期
即使:
所有消费者消费完成
数据仍保留直到:
Retention 到期
十、生产级配置建议(经验总结)
日志流(默认)
cleanup.policy=delete
retention.ms=604800000
segment.ms=3600000
高吞吐系统
retention.bytes=50GB
segment.bytes=512MB
原因:
-
删除更平滑
-
减少 IO spike
状态 Topic(强烈推荐)
cleanup.policy=compact
min.cleanable.dirty.ratio=0.1
Kafka Streams
cleanup.policy=compact,delete
十一、删除策略常见坑(⭐⭐⭐⭐⭐)
1️⃣ retention 设置了但不删除
原因:
segment 未滚动
解决:
降低 segment.ms
2️⃣ 磁盘突然释放大量空间
原因:
Kafka 删除的是大文件 segment
不是渐进删除。
3️⃣ Consumer 报 OffsetOutOfRange
原因:
数据已被 retention 删除
4️⃣ compact 不是实时
Log Cleaner 是后台线程:
最终一致(Eventually Consistent)
十二、一句话总结(架构级)
Kafka 数据删除本质:
Kafka = Immutable Commit Log
+
Retention Policy
+
Segment Lifecycle
即:
Kafka 通过 日志段生命周期管理,而不是消息消费行为,控制数据存活时间。