Kafka Streams - 使用 through() 与 toStream() + to() 重用流

Ric*_*h P 4 apache-kafka apache-kafka-streams

我想知道在 .toStream() + .to() 的流引用上使用 .through() 重用流的区别

使用 .through()

KStream<String, String> subStream = mainStream .groupByKey(..) .aggregate(..) .toStream(..); .through("aggregate-topic", ..); // Then use the (new) stream from .through() to create another topic

对比使用 .toStream() + .to()

KStream<String, String> subStream = mainStream .groupByKey(..) .aggregate(..) .toStream(..); subStream.to("aggregate-topic", ..); //reuse the existing subStream from toStream() to create another topic

我已经实现了一个使用后者的功能,因为在我学习 through() 方法之前,这是有意义的。

我现在好奇的是这两种选择的内部情况;选择一个选项而不是另一个选项有什么好处/坏处吗?

Mat*_*Sax 12

是的,存在差异和不同的权衡:

  1. 使用的第一个版本through()将创建一个“线性计划”并将拓扑拆分为两个子拓扑。请注意,through("topic")这与to("topic")plus完全相同builder.stream("topic")

    mainStream -> grp -> agg -> toStream -> to -> TOPIC -> builder.stream -> subStream

第一子拓扑将从mainStreamto(); 在"aggregate-topic"从第二子拓扑结构包括其分离builder.stream()和饲料进入subStream。这意味着,"aggregate-topic"首先写入所有数据,然后再读回。这将增加端到端处理延迟并增加额外读取操作的代理负载。优点是,两个子拓扑都可以独立并行化。它们的并行性是独立的,并由它们对应的输入主题分区的数量决定。这将创建更多的任务,从而允许更多的并行性,因为两个子拓扑都可以在不同的线程上执行。

  1. 第二个版本将创建一个“分支计划”,并将作为一个子拓扑执行:

    mainStream -> grp -> agg -> toStream -+-> to -> TOPIC | + -> 子流

toStream()数据被逻辑地广播到两个下游运营商之后。这意味着,没有通过 的往返,"aggregate-topic"但记录在内存中转发到subStream。这减少了端到端延迟,并且不需要从 Kafka 集群读回数据。但是,您的任务较少,因此减少了最大并行度。