Kafka Streams:在标点函数中生成的消息的语义仅一次

时间:2019-04-03 17:08:51

标签: apache-kafka apache-kafka-streams

我想使用Kafka流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 changelog主题支持。在每分钟的墙上时钟时间安排标点器。我已经在配置中配置了processing.guarantee=exactly_once

1 个答案:

答案 0 :(得分:2)

如果您使用的是Punctuator,那么语义恰好也适用。

在使用状态存储的情况下,所有要写到changelog主题(甚至删除-使用某些键和null值写消息)

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

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

可以找到更多详细信息: