Kafka Streams处理器-状态存储和输入主题分区

时间:2018-10-10 16:08:37

标签: apache-kafka apache-kafka-streams

我想充分理解kafka-streams处理器在划分处理器输入及其状态时必须遵循的规则。具体来说,我想了解:

  1. 是否有可能,为状态存储库使用与输入主题的密钥不同的密钥有什么潜在的后果
  2. 状态存储键是否在分区之间共享,即,如果在处理属于两个不同分区的记录时尝试访问处理器中的相同键,是否会获得相同的值

我一直在对此进行一些研究,发现的答案似乎不是很清楚,有时甚至是矛盾的: this one似乎暗示商店是完全独立的,并且您可以使用任何键,而this one则说您不应使用与输入主题中的钥匙不同的商店。

感谢您的澄清。

1 个答案:

答案 0 :(得分:3)

您必须区分输入分区,并存储分片/更改日志主题分区以获取完整图片。另外,这取决于您使用DSL还是Processor API,因为DSL会进行一些自动重新分区,但Processor API不会。因为DSL可以编译为Processor API,所以我将从这里开始。

如果您有一个带有4个分区的主题,并且创建了一个使用此主题的有状态处理器,那么您将获得4个任务,每个任务运行一个处理器实例,该实例维护一个存储区。请注意,整体状态分为4个分片,每个分片基本上与其他分片隔离。

从Processor API运行时的角度来看,输入主题分区和状态存储碎片(包括其对应的changelog主题分区)是并行度的单位。因此,将使用4个分区创建商店的changelog主题,并将changelog-topic-partition-X映射到input-topic-partition-X。请注意,Kafka Streams在写入更改日志主题时不会使用基于哈希的分区,但是会明确提供分区号,以确保“处理器实例X”能够处理input-topic-partition- X,仅从changelog-topic-partition-X中读取/写入。

因此,如果需要,运行时与密钥无关。

如果输入主题不是按键划分的,则具有相同键的消息将由不同的任务处理。根据程序的不同,可能没有问题(例如过滤),也可能没有问题(例如每个键计数)。

类似于状态:您可以将任何密钥放入状态存储,但是此密钥对于相应的分片是“本地的”。其他任务,将永远不会看到此键。因此,如果您在商店中使用相同的密钥执行不同的任务,则它们将彼此完全独立(就像它们将是两个密钥一样)。

使用Processor API,您有责任根据所需的运算符语义正确划分输入数据并正确使用存储。

在DSL级别,Kafka Streams将确保正确划分数据以确保正确的操作员语义。首先,假设输入主题按键划分。如果例如通过selectKey()修改了键,并且下游运算符是一个聚合,那么Kafka Streams会首先对数据进行重新分区,以确保具有相同键的记录位于同一主题分区中。这样可以确保每个密钥将在单个存储碎片中使用。因此,DSL将始终对数据进行分区,以使一个密钥永远不会在不同的分片上进行处理。