如何扩展 Kafka Stream 应用程序

How to scale Kafka Stream application

我对kafka文档中关于这个主题的措辞有点困惑,所以我想在这里问一下我在这里解释的是否正确?

因此,如果我理解正确,则扩展 Kafka Stream 应用程序的唯一方法是启动应用程序的新实例(或增加应用程序中的流线程数),这将确保有更多的消费者consumerGroup('application.id'),所以我可以将我的流应用程序扩展到主题的分区数(实际上,如果我的流拓扑连接到多个主题会发生什么,假设 TopicA 有 5 个分区,topicB 有 3 个我加入了TopicA 和 TopicB 的流,我猜在这种情况下我可以扩展到 3 instances/threads)。

现在假设我有一个包含 5 个分区的 topicA,我启动了我的应用程序的 3 个实例,如果我在我的拓扑中配置了 KTable,每个 KTable 都将包含来自特定分区的信息,我必须找出哪些元数据instance(partition) 我的 Key 是,所以当我启动第 4 个实例时会发生什么,假设 Key/Value 是 instance3 上的 KTable 现在可以转到 instance4 上的 KTable,不是吗?一方面的问题是这种重新平衡会持续多长时间(我认为这取决于主题大小,所以假设需要 1 分钟,我正在查询 KTable 的应用程序会不会在此操作期间没有响应?)

附带问题,此机制对 'streamBuilder.table(..)' 和 'streambuilder.groupByKey(..).reduce(..)'' 是否完全相同?

最后一个问题,同样是一个具有 5 个分区的主题,但我没有启动应用程序的 3 个实例,而是启动了一个具有 3 个流线程的实例 (num.stream.threads = 3) 我是否会再次拥有 3 个 KTable 的代表5 个分区,如果我将线程大小 3 更改为 4,它的行为是否与增加实例数完全相同。

感谢解答..

lets say TopicA with 5 partition and topicB with 3 I joined the streams for TopicA and TopicB, I am guessing I can scale up to 3 instances/threads in this case).

首先,为了连接两个主题,它们应该有相同数量的分区。这是加入的关键要求。如果您有 5 个分区的主题 A 和 3 个分区的主题 B,它永远不会执行连接。 (https://docs.confluent.io/current/streams/developer-guide/dsl-api.html#join-co-partitioning-requirements)

what happens when I start a 4th instance,

是的,Kafka 流将根据分区数量重新平衡实例之间的工作负载。它将重新分配分区及其任务,包括本地状态存储。时间取决于主题大小。如果有终端用户查询 ktable,您应该更喜欢从所有实例中收集元数据并执行查找。

will this mechanism works exactly same for 'streamBuilder.table(..)' and 'streambuilder.groupByKey(..).reduce(..)''?

是的,无论何时使用任何转换创建 ktable,都会遵循相同的机制。

again a Topic with 5 partitions but instead of starting 3 instances of the application, I started one instance with 3 stream threads (num.stream.threads = 3) will I have again 3 KTable's representing 5 partitions, will it behave exactly the same as increasing the instances number if I change thread size 3 to 4.

默认情况下,Kafka Streams 会将拓扑分成 5 个任务(=分区数)。如果 num.stream.threads 设置为 3,这些任务将分布在指定的线程中。因此 thread-1 可以 运行 2 个任务,thread-2 可以 运行 接下来的 2 个任务和 thread-3 可以 运行 1 个任务。
KTable 状态将被划分为 5 个分片(=分区数),一个分片将映射到一个任务。因此,每个任务都会创建一个本地存储,不包括自身。这些本地存储包含相应分片的数据。尽管有线程数,您将获得等于分区数的本地存储。

示例:

再添加一个实例后