【问题标题】:Why do the offsets of the consumer-group (app-id) of my Kafka Streams Application get reset after application restart?为什么我的 Kafka Streams 应用程序的消费者组(app-id)的偏移量在应用程序重启后会被重置?
【发布时间】:2019-06-04 02:37:12
【问题描述】:

我有一个 Kafka Streams 应用程序,每当我重新启动它时,它正在使用的主题的偏移量都会被重置。因此,对于所有分区,延迟都会增加,应用需要重新处理所有数据。

更新: 输出主题正在接收应用程序重新启动后已经处理的突发事件,而不是像我在上一段中所说的那样重置输入主题偏移量。但是,内部主题 (KTABLE-SUPPRESS-STATE-STORE) 偏移量正在重置,请参阅下面的 cmets。

我已确保重启前每个分区的延迟为 1(这是针对输出主题的)。 属于该消费者组 ID (app-id) 的所有消费者都处于活动状态。 立即重启,大约需要 30 秒。

应用只使用一次作为处理保证。

我已阅读此答案How does an offset expire for an Apache Kafka consumer group?

我已尝试使用 auto.offset.reset = latestauto.offset.reset = early

这些主题的偏移量似乎没有有效地提交,(但我不确定)。

我假设在重新启动后,应用程序应该从该消费者组的最新提交偏移量中获取。

更新: 我假设这是内部主题(KTABLE-SUPPRESS-STATE-STORE

Kafka Stream API 是否确保在关闭之前提交所有消耗的偏移量? (在调用 streams.close() 之后)

如果能提供任何线索,我将不胜感激。

更新

这是应用程序执行的代码:

final StreamsBuilder builder = new StreamsBuilder();
final KStream<..., ...> events = builder
        .stream(inputTopicNames, Consumed.with(..., ...)
        .withTimestampExtractor(...);

events
    .filter((k, v) -> ...)
    .flatMapValues(v -> ...)
    .flatMapValues(v -> ...)
    .selectKey((k, v) -> v)
    .groupByKey(Grouped.with(..., ...))
    .windowedBy(
        TimeWindows.of(Duration.ofSeconds(windowSizeInSecs))              
            .advanceBy(Duration.ofSeconds(windowSizeInSecs))
            .grace(Duration.ofSeconds(windowSizeGraceInSecs)))
    .reduce((agg, new) -> {
        ...
        return agg;
    })
    .suppress(Suppressed.untilWindowCloses(
                  Suppressed.BufferConfig.unbounded()))
    .toStream()
    .to(outPutTopicNameOfGroupedData, Produced.with(..., ...));

使用 Kafka Stream API 创建的 KTABLE-SUPPRESS-STATE-STORE 内部主题总是会发生偏移重置(重启后)。

我已尝试仅一次至少一次处理保证。

再一次,我将非常感谢有关此的任何线索。

更新: 这已在版本 2.2.1 (https://issues.apache.org/jira/browse/KAFKA-7895)

中解决

【问题讨论】:

  • 你说你不确定偏移量是否真的被提交了。您是否查看过 consumer__offsets 主题来验证这一点?这篇博文可能有助于找出答案:medium.com/@felipedutratine/…
  • 您是否尝试过它是否可以在没有完全一次处理保证的情况下工作?这是一个相对较新的功能。
  • 感谢@user152468 的评论,是的,我已经使用bin/kafka-consumer-groups.sh 工具进行了检查。我没有尝试过其他处理保证,因为在我的情况下我需要一个,但值得尝试只是放弃这可能是问题。但是,如果是的话,我会感到惊讶。
  • 偏移量应该在streams.close() 上提交——尝试验证这一点。此外,如果启用了完全一次,则默认情况下应在 100 毫秒内提交所有偏移量。不知道为什么在启动时没有再次获取偏移量。我建议检查日志——也许将日志级别提高到 DEBUG 以获取更多信息。
  • 您好@MatthiasJ.Sax 感谢您的回复,我在日志中找到了这个:INFO [MI-APP-ID-xxx-StreamThread-4] internals.StoreChangelogReader (StoreChangelogReader.java:215) - 流线程 [MI-APP-ID-xxx-StreamThread-4] 未找到检查点 用于任务 1_5 状态存储 KTABLE-SUPPRESS-STATE-STORE-0000000011 更改日志 MI-APP-ID-KTABLE- SUPPRESS-STATE-STORE-0000000011-changelog-5 开启 EOS。 重新初始化任务并从头恢复其状态。 ...关注下一条评论

标签: apache-kafka apache-kafka-streams


【解决方案1】:

使用 Kafka Stream API 创建的 KTABLE-SUPPRESS-STATE-STORE 内部主题,偏移量重置总是发生(重启后)。

这是当前(2.1 版)预期的行为,因为suppress() 运算符仅在内存中工作。因此,在重新启动时,必须从更改日志主题重新创建抑制缓冲区,然后才能开始处理。

注意,计划在未来的版本中让suppress() 写入磁盘(参见https://issues.apache.org/jira/browse/KAFKA-7224)。这将避免从更改日志主题重新创建缓冲区的开销。

【讨论】:

  • 谢谢@MatthiasJ.Sax,所以,重启后App会从offset 0读取KTABLE-SUPPRESS-STATE-STORE主题是正常的,因此,会通过已处理的输出主题事件的下游?
  • 已经处理的数据不会再向下游发送。更改日志数据只是在处理开始之前添加到抑制存储中。如果数据不会被添加到存储中,您可能会丢失结果(想想,一些记录被添加到抑制缓冲区,但从未发出,并且不需要更新相同的键)。另请注意,抑制逐出是基于事件时间的,如果缓冲区在重新启动时重新加载(事件时间仍然相同),则无需逐出任何内容。
  • 再次感谢@MatthiasJ.Sax,在处理开始之前将更改日志数据添加到抑制存储(我猜是在内存中),始终从 offset 0KTABLE-SUPPRESS-STATE-STORE 主题/b>?。我问是因为日志总是显示偏移量被重置为 0(对于KTABLE-SUPPRESS-STATE-STORE 主题分区)。 KTABLE-SUPPRESS-STATE-STORE 主题分区的偏移量在成功抑制或关闭窗口后没有提交?我希望将从未发出过的记录再次添加到缓冲区中,或者不是那样?非常感谢@MatthiasJ.Sax。
  • (1) 永远不会提交更改日志主题的偏移量 (2) 因为缓冲区在内存中,即使要提交偏移量,也需要忽略这一点并从偏移量零重新加载 - - 否则,缓冲区将无法正确加载(没有任何内容写入本地磁盘 - 它是内存缓冲区 atm)。 “我希望将从未发出过的记录再次添加到缓冲区中,或者不是那样?” -- 这当然是可能的。
  • 谢谢@MatthiasJ.Sax,我会检查的:)
【解决方案2】:

我认为@Matthias J. Sax 的回复涵盖了压制的大部分内容。不过,我需要澄清一件事:当您说“重新启动应用程序”时,您到底做了什么?您是否正常关闭了整个应用程序,然后重新启动它?

【讨论】:

  • 您好@GuozhangWang 感谢您的回复。重新启动涉及在关闭挂钩内停止调用KafkaStreams#.close()的应用程序,然后启动调用java ...命令的应用程序。
  • 这听起来很合理。我认为马蒂亚斯的最后评论是在解释当时的情况。
  • 嗨@GuozhangWang 我在重新启动应用程序时遇到了类似的问题(v2.3.1),重新分区主题有字节输入但没有字节输出,而更改日志主题有巨大的字节输出,没有字节输入。我检查了日志,注意到抑制更改的偏移量被重置为 0。并且状态在 PARTITIONS_REVOKED 和 PARTITIONS_ASSIGNED 之间不断变化。这是预期的吗?我没有看到状态变回 RUNNING。请帮忙!非常感谢!!
  • 要重新启动的状态有多大?从描述来看,抑制缓冲区似乎是从头开始恢复的,需要很长时间,因此导致消费者再次被踢出组。
  • 嗨@GuozhangWang,流量约为150K-180K消息/秒。所以我认为这是一个大国。每次我重新部署构建时,它都会发生。有什么办法可以防止恢复整个抑制缓冲区吗?非常感谢!
【解决方案3】:

提交频率由参数commit.interval.ms 控制。检查您的偏移量是否确实已提交。默认情况下,偏移量每 100 毫秒或 30 秒提交一次,具体取决于您的处理保证配置。签出this

【讨论】:

  • 感谢@senseiwu 的回答。是的,在这种情况下,commit.interval.ms 的值是 100ms(默认到期一次)。我正在用 bin/kafka-consumer-groups.sh 检查消费者位置,在重新启动之前,LAG 为 1,重新启动后,LAG 到屋顶。
  • 检查this 的帖子,尤其是 Matthias J. Sax 2018 年 6 月 21 日 17:24 的 cmets,它详细解释了偏移提交机制
  • 这不是问题的答案。
  • 感谢您的指出。但从这个问题来看,听起来 OP 不确定基于 commit.interval.ms 的定期提交实际上是如何工作的。我仍然不清楚这是否是他有问题的地方,或者偏移量是否像他进一步推测的那样被重置
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2018-10-06
相关资源
最近更新 更多