Kafka Streams Processor API:根据密钥将记录转发到特定的流任务

时间:2018-10-24 09:12:24

标签: apache-kafka apache-kafka-streams

我正在使用以下处理器API拓扑:

Source: STopics (topics: [A, B, C])
  --> P1
Processor: P1 (stores: [P1_Store])
  --> CSink
  <-- STopics
Sink: CSink (topic: Result)
  <-- P1

主题具有整数键,例如 ID 。每个主题 A B C 具有相同数量的分区,例如 N 。我有一个场景,其中具有相同键的记录可以出现在任何源主题中。假设我们有由 P1 处理器创建的 N 个实例(或 N 个流任务),每个实例都有状态存储 P1_Store的本地副本

是否有一种方法可以在运行时确定 P1 的实例数,以便可以将具有相同键的记录发送到同一处理器实例,例如使用 ID%N 将本地状态存储中的先前值用于 ID 键?

更新。我要重新键入所有在主题A处具有空键的记录,并且新的键ID可以出现在任何主题(此处为A,B或C)中。

后续问题::如果我有一个处理器P1的两个父处理器P00和P01。 P00在实例X上运行将密钥更改为123并向前转发,而P01在实例Y上运行并转发密钥123。如何保证来自P00-X和P01-Y的密钥123始终转到P1的同一实例(例如P1- Z,以便123的本地状态存储始终在Z)可用?我不希望P00和P01首先写入中间主题,然后P1从该中间主题读取。有没有其他方法可以实现单一拓扑设计?

1 个答案:

答案 0 :(得分:0)

如果输入主题已经按键进行了分区(如果将ID设置为消息键,则为默认值),则无需执行任何操作。 Kafka Streams会将分区分配给任务,以便保留分区。

尤其是,如果每个主题有N个分区,则将有N个任务,任务0将分配有分区A-0,B-0和C-0,依此类推(即,具有相同编号的分区)来自不同主题的内容会自动合并)。另外,处理器的实例数与任务数相同。任务X的处理器将处理分区A-X,B-X和C-X中的所有记录。

如果ID不是输入主题中的关键字,则需要通过其他主题将ID设置为关键字后,重新分区数据:

// using the DSL
stream.selectKey(...)
      .groupByKey()
      .aggregate(...)

// using Processor API
topology.addSource(...); // read input topics
topology.addProcessor(...); // set ID as key
topology.addSink(...); write to new topic for repartitioning
topology.addSource(...); // read from repartition topic
topology.addProcessor(...); // your processor updating the state