如何使用Kstream DSL .transform()方法访问所有状态存储数据

时间:2019-04-01 19:04:36

标签: java apache-kafka apache-kafka-streams

尝试访问已定义状态存储区中的所有键值,但是在.transform()方法中,我只能使用一个键(即源键)进行访问

KeyValueStore<String, String> SS=context.getStateStore("macs");

SS无法在状态存储区中获取所有键值

SS.get("key1");
SS.get("key2");
SS.get("key3");
SS.get("key4");

4个返回值中只有1个返回值,其余所有返回null

1 个答案:

答案 0 :(得分:1)

  

SS无法在状态存储区中获取所有键值

这是预期的行为。实际上,在分布式Kafka Streams应用程序的运行实例中,跨状态存储的实际实例对Kafka Streams中“逻辑”状态存储中的数据进行了分区(分片)(即使您仅运行1个应用程序实例,例如1个Docker容器)为您的应用程序)。让我在下面解释。

一个简化的示例来说明分区状态存储的性质:如果您的应用程序从具有5个分区的输入主题中读取,则此应用程序的处理拓扑将使用5个流任务,并且每个流任务将获得一个分区的一个分区。 “逻辑”状态存储(请参见Kafka Streams Architecture)。如果仅为您的应用程序运行1个应用程序实例(例如1个Docker容器),则此单个实例将执行所有5个流任务,但这些流任务是无共享设置–这意味着数据仍在分区。 Kafka Streams中的KTable也是如此,它们也以这种方式进行分区。

另请参阅:Is Kafka Stream StateStore global over all instances or just local?

您的上述示例仅在输入主题仅具有1个分区的特殊情况下才有效,因为那时只有1个流任务,因此只有1个状态存储(可以访问输入数据中的所有可用键) )。

  

尝试访问已定义状态存储中的所有键值[...]

现在,如果您确实想访问输入数据中的所有可用键,则有两个选择(除非您想沿用只有一个分区的输入主题的特殊情况):

  • 选项1:,请使用全局状态存储(或GlobalKTable),而不是常规的分区状态存储。可以通过StreamsBuilder#addGlobalStore(...)定义/创建全局状态存储,但是IIRC不需要显式地将全局存储添加(“附加”)到Processor中,而对于正常状态存储则必须这样做。相反,所有处理器都可以自动访问全局存储。
  • 选项2:在Kafka Streams中使用interactive queries feature(也称为可查询状态)。

请注意,在这两个选项中,您只能访问状态存储中的数据 。在这两种情况下,您不能直接写入状态存储。如果需要修改数据,则必须通过用于填充商店的输入主题间接更新它们。