Apache kafka 卡夫卡消费者收到的旧消息很少(并非全部)(之前已经处理过)

Apache kafka 卡夫卡消费者收到的旧消息很少(并非全部)(之前已经处理过),apache-kafka,consumer,Apache Kafka,Consumer,我们的主题保留期设置为7天(168小时)。当生产者发送消息时,消息被实时消耗。一切正常。然而,最近在一台生产服务器上,Devops作为操作系统补丁的一部分,意外地将时区从PST更改为EST 在Kafka服务器重启后,我们看到消费者很少(不是全部,而是随机)使用旧消息。我们要求Devops将其更改回PST并重新启动。本周末,旧消息再次出现 我们在较低的环境(开发、质量保证、阶段等)中没有看到这个问题 卡夫卡版本:卡夫卡2.12-0.11.0.2 非常感谢您的帮助 正在添加更多信息。。。最近,我们的

我们的主题保留期设置为7天(168小时)。当生产者发送消息时,消息被实时消耗。一切正常。然而,最近在一台生产服务器上,Devops作为操作系统补丁的一部分,意外地将时区从PST更改为EST

在Kafka服务器重启后,我们看到消费者很少(不是全部,而是随机)使用旧消息。我们要求Devops将其更改回PST并重新启动。本周末,旧消息再次出现

我们在较低的环境(开发、质量保证、阶段等)中没有看到这个问题

卡夫卡版本:卡夫卡2.12-0.11.0.2

非常感谢您的帮助

正在添加更多信息。。。最近,我们的CentOS进行了补丁更新,不知何故,管理员从PST时区更改为EST并启动了Kafka服务器。。。之后,我们的消费者开始看到来自偏移量0的消息。调试后,我发现时区发生了变化,管理员在4天后从EST改回PST。我们的消息制作人定期在时区更改前后发送消息。时区从EST改回PST后,卡夫卡服务器重新启动,我看到下面的警告

当我们从EST切换回PST时,发生了这个日志:(server.log) [2018-06-13 18:36:34430]警告发现由于要求失败而损坏的索引文件:发现损坏的索引,索引文件(/app/kafka_2.12-0.11.0.2/data/_消费者_offsets-21/0000000000000000000000 2076.index)大小非零,但最后一个偏移量为2076,不大于基本偏移量2076。}。删除/app/kafka_2.12-0.11.0.2/data//uuuu consumer_offsets-21/000000000000000002076.timeindex、/app/kafka_2.12-0.11.0.2/data//uuuu consumer_offsets-21/00000000000000000000000076.index和/app/kafka_2.12-0.11.0.2/data//uu consumer_offsets-21/000000000000000002076.txnindex和重建索引。。。(kafka.log.log)


在时区从EST更改回PST的3天后,我们重新启动了消费者,并再次看到偏移量为0的消费者消息。

我认为这是因为您将在提交新偏移量之前重新启动程序

管理补偿

对于每个使用者组,Kafka为每个正在使用的分区维护提交的偏移量。当使用者处理消息时,它不会将其从分区中删除。相反,它只是使用称为提交偏移量的过程更新其当前偏移量

如果使用者在处理消息后但在提交其偏移量之前失败,则提交的偏移量信息将不会反映消息的处理。这意味着该组中要分配分区的下一个使用者将再次处理该消息

自动提交偏移量

提交偏移量的最简单方法是让Kafka使用者自动执行。这很简单,但与手动提交相比,它提供的控制更少。默认情况下,使用者每5秒自动提交一次偏移。此默认提交每5秒发生一次,与使用者处理消息的进度无关。此外,当使用者调用
poll()
时,这也会导致提交上次调用
poll()
返回的最新偏移量(因为它可能已被处理)

如果提交的偏移量超过了对消息的处理,并且存在使用者故障,则可能无法处理某些消息。这是因为处理将在提交的偏移量处重新启动,该偏移量晚于故障前要处理的最后一条消息。因此,如果可靠性比简单性更重要,通常最好手动提交偏移量

手动提交偏移量

如果‍
enable.auto.commit
设置为false,使用者手动提交其偏移量。它可以同步或异步执行此操作。一种常见的模式是基于周期计时器提交最新处理的消息的偏移量。此模式意味着每个消息至少处理一次,但提交的偏移量永远不会超过正在处理的消息的进度。周期计时器的频率控制消费者故障后可重新处理的消息数量。当应用程序重新启动或组重新平衡时,将再次从上次保存的提交偏移量中检索消息

提交的偏移量是从中恢复处理的消息的偏移量。这通常是最近处理的消息的偏移量加上一

我认为这非常有帮助。

就像卡夫卡v2.3.0一样 你可以设置

    "enable.auto.commit" : "true",// default is true as well
    "auto.commit.interval.ms" : "1000"
这意味着,在每1秒之后,使用者将向Kafka提交其偏移量,或者每次从指定主题获取数据时,使用者将提交最新的偏移量


因此,您的卡夫卡消费者一旦启动且1秒过后,它将永远不会读取消费者收到的和承诺的消息。此设置不需要重新启动Kafka服务器。

是否使用
消费者组
?是的,我们有两个消费者,并且都使用相同的consumer.id。我刚刚查看了代码,消费者应用程序并没有关闭KafkaConsumer作为应用程序关闭的一部分。但是,在使用这些消息之后,我们正在提交它。当我们重新启动消费者应用程序时,重复/旧消息偶尔出现一次。使用Kafka(0.11.0.2)和Java客户端API版本为1.0。enable.auto.commit=false并以编程方式进行comitting->consumer.commitSync()@user1114134你有没有发现?我们正在调用consumer.commitAsync();(我们已经记录了“提交前”和“提交后”的日志消息。这是正确记录的)。而且,我们没有看到