首页/数据/数据工程与 ETL 速查/日志压实 Log Compaction
Kafka64 条

日志压实 Log Compaction

压实(cleanup.policy=compact)按键保留最新一条消息,适合变更日志与状态快照;删除通过写入带 null 值的 tombstone 消息表达。

日志压实是什么

压实是 Kafka 的一种日志清理策略:主题设置 cleanup.policy=compact 后,后台会按键归并,同一 key 只保留最后一条 value,更早的记录最终被清除。它解决的是「这个主题表达的是状态而不是事件流」的场景——变更日志、配置下发、按主键的最新值快照。删除一条记录不是真的删行,而是写入一条 value 为 null 的消息(称为 tombstone),让压实过程把该 key 一并清掉。

基本信息

语义同一 key 只保留最后一个 value(更早的最终被清理)
典型场景KTable changelog、配置变更流、CDC 明细表
相关参数min.cleanable.dirty.ratio、delete.retention.ms、segment.ms
混合策略cleanup.policy=compact,delete 可同时按时间清理
删除方式写入 key 相同、value 为 null 的消息
偏移特性压实后偏移不连续,出现空洞

创建压实主题

创建压实主题
kafka-topics.sh --bootstrap-server localhost:9092 \
  --create --topic user-profile-compact \
  --partitions 3 --replication-factor 3 \
  --config cleanup.policy=compact \
  --config min.cleanable.dirty.ratio=0.3

# 把已有主题改成压实策略
kafka-configs.sh --bootstrap-server localhost:9092 --alter \
  --entity-type topics --entity-name user-profile --add-config cleanup.policy=compact

# 查看生效配置
kafka-configs.sh --bootstrap-server localhost:9092 --describe \
  --entity-type topics --entity-name user-profile

典型使用场景

  • 状态快照:下游重启后重放主题即可恢复每个 key 的最新状态
  • 配置下发:同一配置项只关心最终值,中间版本不需要长期保留
  • CDC 明细同步:按主键保留最新一行,降低下游存储与读取压力
  • 缓存预热:消费端重建本地缓存时不必重放全部历史变更
  • 存储控制:相比 delete 策略,compact 能在保留语义的同时显著减小体积

关键参数读法

参数含义注意
cleanup.policy清理策略compact、delete 或两者并用
min.cleanable.dirty.ratio触发压实的脏数据比例阈值越小越频繁,写放大越高
delete.retention.mstombstone 保留时长重放窗口要覆盖该保留期
segment.ms日志段滚动时间段过大压实粒度变粗
max.compaction.lag.ms压实最大延迟用于限制 key 长时间不被清理
压实只保证最终收敛:key 的旧值在被清理前仍然可以被读到,重放时要按 key 去重取最新。
压实不会在消息写入后立即发生,触发条件与段的脏数据比例有关;对时效敏感的场景不能依赖压实作为「删除」的手段,删除本身要发 tombstone。

易错点

  • 压实主题的空隙不会被自动回收,读端要靠 key 归并,不能假设「只有一条」
  • tombstone 会保留 delete.retention.ms 后消失,重放时间窗口要覆盖该保留期
  • 把需要完整事件历史的主题设置成 compact,早期记录被清理后无法回放
  • 用 compact 主题承载大体量明细,压实线程与磁盘压力都会显著上升
  • 期望压实立刻生效,结果短时间内仍能读到旧值,误判为清理失败

数据来源与参考

  • Apache Kafka 官方文档:Log Compaction
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌