基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Kafka 的日志清理策略有哪些?

知识点图片

Kafka 的日志清理(Log Cleanup)是管理磁盘空间、确保系统稳定运行的核心机制。因为 Kafka 会将消息持久化到磁盘上,如果不进行清理,磁盘空间最终会被耗尽。

Kafka 提供了两种主要的日志清理策略,由配置参数 cleanup.policy 来控制:Delete(删除策略)Compact(压缩/压实策略)。此外,还可以将两者混合使用

需要特别注意的是:所有的清理策略都只针对“非活跃的日志分段(Inactive Log Segments)”生效,当前正在写入的活跃分段(Active Segment)是绝对不会被清理的。

以下是详细的策略解析:


1. 删除策略(Delete Policy)

配置项cleanup.policy = delete(这是 Kafka 的默认策略

核心思想:直接删除旧的日志分段(Segment)。Kafka 允许根据时间文件大小来决定何时删除数据。

A. 基于时间的保留(Time-based Retention)

Kafka 会定期检查日志分段的最后修改时间,如果超过了设定的阈值,就会将其删除。

  • 配置参数(优先级从高到低:ms > minutes > hours):
    • log.retention.ms:毫秒级别。
    • log.retention.minutes:分钟级别。
    • log.retention.hours:小时级别(默认值为 168 小时,即 7天)。
  • 适用场景:绝大多数普通的事件流、日志收集系统。例如:“我们只需要保留最近一周的用户行为数据”。

B. 基于大小的保留(Size-based Retention)

Kafka 会检查每个 Partition(分区) 的总日志大小,如果超过了设定的阈值,就会从最旧的日志分段开始删除,直到分区大小降到阈值以下。

  • 配置参数
    • log.retention.bytes:限制单个 Partition 的最大字节数。默认值为 -1(即不限制大小)。
  • 注意:这个大小限制是作用于单个分区的,而不是整个 Topic 或整个 Broker 集群。

C. 触发机制

Kafka 会启动一个后台定时任务来检查是否需要删除日志。

  • 配置参数log.retention.check.interval.ms(默认 5 分钟检查一次)。

2. 压缩/压实策略(Compact Policy)

配置项cleanup.policy = compact

核心思想:不直接丢弃旧数据,而是针对每个 Key 保留最新的一条 Value。如果一条消息有相同的 Key,较旧的 Key-Value 将被清理掉,就像 HashMap 一样覆盖旧值。

前提条件:消息必须要有 Key(key != null)。

A. 工作原理

  1. 日志被分为两部分:已清理部分(Clean)未清理部分(Dirty)
  2. 后台的 Log Cleaner 线程会扫描未清理部分,将 Key 及其最新的 Offset 放入一个内存哈希表中。
  3. 接着,Cleaner 线程会重新拷贝日志分段,在拷贝过程中,如果发现某条消息的 Offset 比内存哈希表中的 Offset 小(说明有更新的值),就会将该旧消息丢弃。
  4. 最终生成一个物理上更小的新日志分段。

B. 如何彻底删除一个 Key?(墓碑消息 Tombstone)

既然 Compact 策略是保留最新的值,那如果我想彻底删除某个 Key 怎么办?

  • 做法:向 Kafka 发送一条该 Key 的消息,并将 Value 设置为 null(这种消息被称为 墓碑消息 Tombstone)。
  • 机制:Log Cleaner 发现墓碑消息后,会将其作为该 Key 的最新状态保留一段时间(由 log.cleaner.delete.retention.ms 控制,默认 24 小时),确保消费者有足够的时间读取到这个“删除事件”。超时后,墓碑消息本身也会被物理删除,这个 Key 就彻底消失了。

C. 触发条件

并不是只要有相同 Key 就立刻压缩,只有当“脏数据”(未压缩数据)达到一定比例时才会触发。

  • 配置参数min.cleanable.dirty.ratio(默认 0.5,即脏数据占总数据 50% 时触发压缩)。

D. 适用场景

  • 保存系统最新状态:例如保存用户的最新余额、商品的最新库存。
  • CDC(变更数据捕获):同步数据库的变更日志(Debezium 等工具常用)。
  • Kafka 内部的 Offset 存储:著名的内部 Topic __consumer_offsets 默认就是使用的 compact 策略。

3. 混合策略(Delete + Compact)

配置项cleanup.policy = delete,compact

核心思想:结合上述两者的特点。

  • 一方面,日志 Cleaner 线程会持续对具有相同 Key 的数据进行压缩,保留最新状态。
  • 另一方面,如果某个日志分段整体满足了基于时间或基于大小的删除条件(例如超过了 7 天),该日志分段还是会被整体物理删除

适用场景
既想维持数据的最新状态,又不想永久保存僵尸数据。例如:“我想保留每个用户最近的登录位置(Compact),但我只关心最近 30 天内活跃过的用户(Delete)”。


总结与对比

策略 机制 适用场景 消息是否需要 Key 磁盘空间控制
Delete (删除) 按时间或大小整体抛弃旧分段 普通消息、行为日志、访问日志等流水型数据 不需要 精确,可控性极高
Compact (压缩) 相同 Key 只保留最新的 Value 状态表、缓存刷新、数据库 CDC 数据同步 必须有 取决于 Key 的数量(Key 越多,占用越大)
混合 既做状态压缩,也做定时删除 有时间窗口要求的状态同步 必须有 精确可控

配置级别
清理策略既可以在 Broker 级别(全局默认)通过 server.properties 配置,也可以在 Topic 级别 通过 Kafka 命令动态修改覆盖(推荐做法)。

00:00
00:00