Kafka日志压缩原理

Kafka可以根据日志的时间或大小删除旧的记录。Kafka还支持用于记录键压缩的日志压缩。日志压缩意味着Kafka在日志压缩期间将保留一个记录的最新版本,并删除旧版本。

Kafka日志压缩

对于单个主题分区,日志压缩(log compaction)至少保留每个记录键的最后一个已知值。压缩日志对于在崩溃或系统故障后恢复状态非常有用。

它们在内存服务、持久数据存储、重新加载缓存等方面很有用。数据流的一个重要用例是记录对键控的、可变的数据对数据库表的更改,或者对内存微服务中的对象的更改。

日志压缩是一种粒度保留机制,它保留每个key的最后更新。日志压缩主题日志包含每个记录键的最终记录值的完整快照,而不仅仅是最近更改的键。

Kafka日志压缩允许下游消费者从日志压缩主题恢复他们的状态。

Kafka日志压缩结构

对于压缩日志,日志有头和尾。压缩日志的头部与传统的Kafka日志相同。新记录被附加到头部的末尾。

所有日志压缩都在日志的尾部工作。日志尾部的记录在用压缩清理重写后写入时保留其原始偏移量。

Kafka日志压缩基础

所有压缩的日志偏移量仍然有效,即使在偏移量处的记录已经被压缩掉,因为消费者将得到下一个最高的偏移量。

Kafka日志压缩也允许用于删除。带有一个键(key)和一个空有效负载的消息就像一个墓碑,即该键的删除标记。一段时间后,墓碑会被清除。通过复制日志段,日志压缩定期在后台运行。压缩不会阻塞读取,可以对其进行限制,以避免影响生产者和消费者的I/O。

Kafka日志压缩清理

如果Kafka消费者一直在日志的头部,它会看到所写的每一条记录。

主题配置min.compaction.lag.ms用于保证压缩消息之前必须经过的最小周期。只要消费者在小于主题配置delete.retention.ms(默认是24小时)的时间段内到达日志头部,消费者就会看到所有的墓碑。日志压缩永远不会重新排序消息,只是删除一些。消息的分区偏移量永远不会改变。

任何从日志开始读取的消费者都至少会看到所有记录的最终状态(按照它们被写入的顺序)。

Kafka日志清理器

回忆一下,Kafka主题有一个日志。一个日志被划分为多个分区(partitions),分区又被划分为多个段(segments),这些段包含有键和值的记录(records)。

Kafka日志清理器(Kafka Log Cleaner)执行日志压缩。日志清理器有一个后台压缩线程池。这些线程重新复制日志段文件,删除其键最近在日志中重新出现的旧记录。每个压缩线程选择日志头与日志尾比例最高的主题日志。然后压缩线程从头到尾复制日志,删除那些键在日志中稍后出现的记录。

当日志清理器清理日志分区段时,这些段被交换到日志分区中,立即替换旧的段。通过这种方式,压缩并不需要整个分区的两倍空间,因为所需的额外磁盘空间只是一个额外的日志分区段——分治即可。

日志压缩的主题配置

要打开一个主题的压缩,请使用主题配置log.cleanup.policy=compact。

要设置延迟在记录完成后开始压缩记录,请使用主题配置log.cleaner.min.compact.lag.ms。直到这段时间之后,记录才会被压缩。该设置为消费者提供了获取每条记录的时间。

日志压缩常见问题

问:Kafka删除记录的三种方式是什么?

答:Kafka可以根据日志的时间或大小删除旧的记录。Kafka还支持用于记录键压缩的日志压缩。

问:日志压缩有什么好处?

由于日志压缩保留了最近的已知值,它是最新记录的完整快照,因此对于内存服务、持久数据存储或重新加载缓存的崩溃或系统故障后恢复状态非常有用。它允许下游消费者恢复其状态。

问:压缩的日志的数据结构是什么?描述该结构。

答:对于压缩日志,日志有头和尾。压缩日志的头部与传统的Kafka日志相同。新记录被附加到头部的末尾。所有日志压缩都在压缩日志的尾部工作。

问:压缩后,日志记录偏移量是否改变?

答:不改变。

问:什么是分区段?

答:回忆一下,一个主题有一个日志。一个主题日志被划分为多个分区,分区又被划分为包含有键和值的记录的段文件。当涉及到日志压缩时,段文件允许分治。段文件是分区的一部分。当日志清理器清理日志分区段时,这些段被交换到日志分区中,立即替换旧的段文件。这样压缩并不需要整个分区的两倍空间,因为需要的额外磁盘空间只是一个额外的日志分区段。


《Flink原理深入与编程实战》