阅读 Kafka Streams DSL 中的分区主题

Reading already partitioning topic in Kafka Streams DSL

在 Kafka Streams 中重新分区高容量主题可能非常昂贵。一种解决方案是在生产者端通过键对主题进行分区,并在 Streams 应用程序中摄取一个已经分区的主题。

有没有办法告诉 Kafka Streams DSL 我的源主题已经按给定键分区并且不需要重新分区?


让我澄清一下我的问题。假设我有一个像这样的简单聚合(为简洁起见省略了细节):

builder
    .stream("messages")
    .groupBy((key, msg) -> msg.field)
    .count();

鉴于此代码,Kafka Streams 将读取 messages 主题并立即将消息写回内部重新分区主题,这次按 msg.field 作为键进行分区。

一个简单的方法来使这个往返过程变得不必要,那就是首先编写由 msg.field 分割的原始 messages 主题。但是 Kafka Streams 对 messages 主题分区一无所知,我发现没有办法在不引起真正重新分区的情况下告诉它主题是如何分区的。

请注意,我并不是要完全消除分区步骤,因为主题 必须分区 才能计算键控聚合。我只想将分区步骤从 Kafka Streams 应用程序上游转移到原始主题生产者。

我要找的基本上是这样的:

builder
    .stream("messages")
    .assumeGroupedBy((key, msg) -> msg.field)
    .count();

其中 assumeGroupedBy 会将流标记为 已经 msg.field 分区。我知道这个解决方案有点脆弱,会在分区键不匹配时中断,但它解决了处理大量数据时的问题之一。

问题更新后更新:如果您的数据已经根据需要进行分区,而您只是想聚合数据而不进行重新分区操作(两者都适用于您的使用case),那么你只需要使用 groupByKey() 而不是 groupBy()。尽管 groupBy() 总是会导致重新分区,但它的同级 groupByKey() 假定输入数据已经根据现有消息键按需要进行了分区。在您的示例中,如果 key == msg.field.

groupByKey() 将起作用

原回答如下:

Repartitioning a high-volume topic in Kafka Streams could be very expensive.

是的,没错——它可能非常昂贵(例如,当高容量意味着每秒数百万个事件时)。

Is there a way to tell Kafka Streams DSL that my source topic is already partitioned by the given key and no repartition is needed?

除非您指示,否则 Kafka Streams 不会对数据进行重新分区;例如,使用 KStream#groupBy() 函数。因此,没有必要像您在问题中所说的那样告诉它“不要分区”。

One solution is to partition the topic by a key on the producer’s side and ingest an already partitioned topic in Streams app.

鉴于您的这种解决方法,我的印象是您提出问题的动机是另外一回事(您必须考虑到具体情况),但您的问题文本并未明确说明可能是什么。也许您需要用更多细节更新您的问题?