Kafka:消息从主题中消失,最大时间=0

Jos*_*dao 2 apache-kafka apache-zookeeper

我们发现 Apache Kafka 2.3、2.4.0、2.4.1 和 2.5.0 版本的主题中的消息消失了。当我们对集群进行滚动部署时,我们注意到了这一点,不幸的是它并不是每次都会发生,所以它非常不一致。

有时我们会丢失主题内的所有消息,有时我们会丢失分区内的所有消息。当发生这种情况时,以下日志是一个常量:

[2020-04-27 10:36:40,386] INFO [Log partition=test-lost-messages-5, dir=/var/kafkadata/data01/data] Deleting segments List(LogSegment(baseOffset=6, size=728, lastModifiedTime=1587978859000, largestTime=0)) (kafka.log.Log)
Run Code Online (Sandbox Code Playgroud)

之前还有一份日志称该段的保留时间超出了 24 小时。在此示例中,该消息是在部署前大约 12 分钟生成的。

请注意,所有被错误删除的消息largestTime=0和被正确删除的消息都有一个有效的时间戳。从我们从文档和代码中读到的内容来看,它似乎largestTime用于计算给定段是否达到时间违规。

由于我们可以在 Kafka 的多个版本中观察到这一点,因此我们认为这可能与 Kafka 外部的任何内容有关。例如动物园管理员。

有谁知道为什么会发生这种情况?我们使用的是 Zookeeper 3.6.0。

Jos*_*dao 5

我们发现原因与Kafka本身无关,而是与我们存储日志的卷有关。尽管如此,以下解释可能对教育目的有用:

.timeindex具体来说,这是一个权限问题,当触发日志清理器时,Kafka 无法读取文件。这导致largestTime某些0邮件在保留时间之前被删除。

每个主题分区被分为几个段,最后一个段被存储到.log包含实际消息的不同文件中。对于每个.log文件,都有一个.timeindex包含 offset 和 之间的映射的文件lastModifiedTime

当Kafka需要检查一个段是否可删除时,它会搜索最近的偏移量lastModifiedTime并将其存储为largestTime。然后,检查是否达到保留限制:currentTime - largestTime > retentionTime

如果是,则删除该段和相应的消息。

由于 Kafka 无法读取该文件,largestTime因此0检查currentTime > retentionTime对于我们的 1 天保留始终是正确的。