繁体   English   中英

Kafka Streams - 指向同一主题的所有实例本地商店

[英]Kafka Streams - all instances local store pointing to the same topic

我们有以下问题:

我们想听某些Kafka主题并构建它的“历史” - 所以对于指定的密钥提取一些数据,将其添加到该密钥的现有列表中(或者如果它不存在则创建一个新的)将它放到另一个主题,它只有一个分区,并且是高度压缩的。 另一个应用程序可以只听取该主题并更新它的历史列表。

我在想它如何适应Kafka流库。 我们当然可以使用聚合:

msgReceived.map((key, word) -> new KeyValue<>(key, word))
           .groupBy((k,v) -> k, stringSerde, stringSerde)
           .aggregate(String::new,
                     (k, v, stockTransactionCollector) -> stockTransactionCollector + "|" + v,
                     stringSerde, "summaries2")
           .to(stringSerde, stringSerde, "transaction-summary50");

它创建了一个由Kafka支持的本地存储,并将其用作历史表。

我担心的是,如果我们决定扩展这样的应用程序,每个运行的实例将创建一个新的支持主题${applicationId}-${storeName}-changelog (我假设每个应用程序都有不同的applicationId )。 每个实例开始使用输入主题,获取不同的键集并构建状态的不同子集。 如果Kafka决定重新平衡,一些实例将开始错过本地商店中的一些历史状态,因为它们会获得一组全新的分区。

问题是,如果我只为每个正在运行的实例设置相同的applicationId,它是否应该最终重放来自同一个kafka主题的所有数据,每个运行的实例具有相同的本地状态?

为什么要创建具有不同ID的多个应用程序来执行相同的工作? Kafka实现并行的方式是通过任务:

应用程序的处理器拓扑通过将其分解为多个任务来扩展。

更具体地说,Kafka Streams基于应用程序的输入流分区创建固定数量的任务,每个任务分配来自输入流的分区列表(即Kafka主题)。 分区到任务的分配永远不会改变,因此每个任务都是应用程序的固定平行单元。

然后,任务可以根据分配的分区实例化自己的处理器拓扑; 它们还为每个分配的分区维护一个缓冲区,并从这些记录缓冲区一次一个地处理消息。 因此,流任务可以独立并行地处理,无需人工干预。

如果您需要扩展应用程序,则可以启动运行相同应用程序的新实例(相同的应用程序ID),并且一些已分配的任务将重新分配给新实例。 本地状态存储的迁移将由库自动处理:

当重新分配发生时,一些分区 - 以及它们相应的任务(包括任何本地状态存储) - 将从现有线程“迁移”到新添加的线程。 因此,Kafka Streams在Kafka主题分区的粒度下有效地重新平衡了应用程序实例之间的工作负载。

我建议你看一下本指南

我担心的是,如果我们决定扩展这样的应用程序,每个运行的实例将创建一个新的支持主题$ {applicationId} - $ {storeName} -changelog(我假设每个应用程序都有不同的applicationId)。 每个实例开始使用输入主题,获取不同的键集并构建状态的不同子集。 如果Kafka决定重新平衡,一些实例将开始错过本地商店中的一些历史状态,因为它们会获得一组全新的分区。

一些假设不正确:

  • 如果您运行应用程序的多个实例来扩展应用程序,则所有实例都必须具有相同的应用程序ID(参见Kafka的使用者组管理协议) - 否则,将不会共享加载,因为每个实例都将被视为自己的应用程序,并且每个实例都将分配所有分区。

因此,如果所有实例都使用相同的应用程序ID,则所有正在运行的应用程序实例将使用相同的更改日志主题名称,因此,您打算执行的操作应该是开箱即用的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM