【问题标题】:Kafka Streams: Exactly-once semantics for messages generated in a punctuator functionKafka Streams:在标点函数中生成的消息的 Exactly-once 语义
【发布时间】:2019-08-25 07:23:14
【问题描述】:

我想使用 Kafka Streams Processor API 并在预定的 punctuator function 中每分钟生成一些消息。 Kafka Streams 能否保证这些消息只写入输出主题一次?

我知道在 Kafka Streams 中可以进行一次性处理,因为它通过以下操作进行单个事务:

  1. 向输入主题提交偏移量
  2. 将结果写入输出主题

这个概念是否扩展到处理器 API 中的标点符号函数,没有相关的输入消息需要提交?

例如,此标点符号函数迭代 key value state store 中的项目。每个项目都从存储中删除并转发到下游:

override def punctuate(timestamp: Long) : Unit =
  store.all.asScala.foreach { keyValue =>
      store.delete(keyValue.key)
      context.forward(keyValue.key, keyValue.value)
  }

商店中的每条消息都应该在输出主题上出现一次,即使在处理器发生故障并重新启动的情况下也是如此。

假设存储是持久的;它由 kafka 更改日志主题支持。标点符号按每分钟挂钟时间安排。我在我的配置中配置了processing.guarantee=exactly_once

【问题讨论】:

    标签: apache-kafka apache-kafka-streams


    【解决方案1】:

    如果您使用 Punctuator,则恰好一次语义也适用。

    在后台使用状态存储即将写入更改日志主题(甚至删除 - 使用某些键和 null 值写入消息)

    在您的用例中,Kafka Streams 将从某个输入主题读取消息并写入输出主题和某个更改日志主题(对状态存储的操作)。

    如果您在 Kafka Streams 中仅启用一次,它将在 transaction 模式下工作。使用事务 - 原子多分区写入 - Kafka Streams 确保在执行偏移提交时,将结果写入输出主题,并且状态存储也闪现到代理上的更改日志主题。以上操作是原子的,因此如果其中一个操作失败,应用程序将从先前的偏移位置重新处理消息。以上所有操作都将起作用,因为 Processor::processPunctuator::punctuate(...) 在特定分区的单个线程中执行。

    更多细节可以找到:

    【讨论】:

    • 好吧。是和不是。虽然对存储或转发记录的更新是当前事务的一部分,但您无法保证 何时 会调用标点符号。因此,它取决于标点回调的逻辑。如果程序重新处理旧数据,标点符号可能会在处理过程中的不同点被调用,因此运行之间的结果可能会有所不同。因此,即使您在每次单独运行时都得到类似的结果,程序也不再使用标点符号来确定性。
    猜你喜欢
    • 2019-08-25
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    相关资源
    最近更新 更多