Kafka日志压缩(Log Compaction)
请解释Kafka的日志压缩(Log Compaction)机制,它是如何工作的?什么场景下需要开启日志压缩?
回答
Yahuda
日志压缩定义: 一种基于Key的去重机制,在日志中只保留每个Key的最新一条消息,旧版本的相同Key消息被删除。
与普通清理的区别:
- 普通清理(Deletion): 基于时间或文件大小删除旧Segment
- 日志压缩(Compaction): 基于Key保留最新版本,保证Key的最终状态
工作原理:
1. 两个指针机制:
- Cleaner Point: 已清理的位置
- Log Head: 当前写入位置
- 已清理区域内每个Key只保留最新值
2. 压缩过程:
- Kafka后台的Cleaner线程扫描老日志Segment
- 构建一个Map(Key→最新Offset/Value)
- 排除被清除的Key,生成新的Segment替换旧的
- 在Segment文件中写入**Tombstone(墓碑标记)**标记删除的消息
3. 压缩配置:
// Topic配置
cleanup.policy=compact
// 或同时支持delete和compact
cleanup.policy=compact,delete
// 最小/最大保留的脏消息比例
min.cleanable.dirty.ratio=0.5 // 脏数据比例超50%才触发压缩
// 压缩线程数
log.cleaner.threads=1
使用场景:
- 数据库变更日志(CDC): 保存每个Key的最新状态(如用户信息的变更)
- 配置管理: Topic存储配置变更,消费者只需知道最新配置
- 表状态同步: 用Kafka Topic作为两个系统的状态同步通道
- 恢复场景: Consumer从最早Offset消费时可以获取每个Key的最终状态
与传统数据库对比:
- 不是完整意义上的Upsert(不支持随机更新)
- 是异步的、尽力而为的压缩
- 最终一致,不保证实时返回最新值
- 压缩是分批进行的,不影响实时读写