Apache kafka Kafka Streams:处理来自不同分区的消息时的事件时间偏移 让我们考虑一个具有多个分区和消息的主题,在没有任何特定的分区方案的情况下,以事件时间顺序写入消息。Kafka Streams应用程序对这些消息进行一些转换,然后根据某个键进行分组,然后根据具有给定宽限期的事件时间窗口聚合消息

Apache kafka Kafka Streams:处理来自不同分区的消息时的事件时间偏移 让我们考虑一个具有多个分区和消息的主题,在没有任何特定的分区方案的情况下,以事件时间顺序写入消息。Kafka Streams应用程序对这些消息进行一些转换,然后根据某个键进行分组,然后根据具有给定宽限期的事件时间窗口聚合消息,apache-kafka,apache-kafka-streams,Apache Kafka,Apache Kafka Streams,每个任务可以以不同的速度处理传入消息(例如,因为在具有不同性能特征的服务器上运行)。这意味着,在groupBy shuffle之后,当内部主题的同一分区中的消息来自不同的任务时,它们之间的事件时间顺序将不会保留。一段时间后,此事件时间偏差可能会大于宽限期,这将导致丢弃来自滞后任务的消息 增加宽限期似乎不是一个有效的选项,因为它会延迟发送最终聚合结果。ApacheFlink通过在合并分区时发出最低的水印来处理这个问题 这应该是一个真正的问题,特别是在处理大量历史数据时,还是我遗漏了什么?Kafka

每个任务可以以不同的速度处理传入消息(例如,因为在具有不同性能特征的服务器上运行)。这意味着,在groupBy shuffle之后,当内部主题的同一分区中的消息来自不同的任务时,它们之间的事件时间顺序将不会保留。一段时间后,此事件时间偏差可能会大于宽限期,这将导致丢弃来自滞后任务的消息

增加宽限期似乎不是一个有效的选项,因为它会延迟发送最终聚合结果。ApacheFlink通过在合并分区时发出最低的水印来处理这个问题

这应该是一个真正的问题,特别是在处理大量历史数据时,还是我遗漏了什么?Kafka Streams是否提供了一种解决方案来应对这种情况

更新我的问题不是关于KStream KStream连接,而是关于流洗牌之前的单个KStream事件时间聚合

考虑以下代码片段:

stream
  .mapValues(...)
  .groupBy(...)
  .windowedBy(TimeWindows.of(Duration.ofSeconds(60)).grace(Duration.ofSeconds(10)))
  .aggregate(...)
我假设mapValues()操作对于某些任务来说可能会很慢,不管是什么原因,因为这些任务会以不同的速度处理消息。当在
aggregate()
操作符上发生洗牌时,任务0可以在任务1仍处于
t-skew
时处理到
t的消息,但来自两个任务的消息最终在内部主题的单个分区中交错(对应于分组键)


我担心的是,当倾斜足够大(在我的示例中超过10秒)时,来自滞后任务1的消息将被丢弃。

基本上,任务/处理器维护一个流时间,它被定义为任何已轮询记录的最高时间戳。然后,该流时间在卡夫卡流中用于不同的目的(例如:点集、窗口聚合等)

[窗口聚合]

如您所述,流时间用于确定是否应接受记录,即记录被接受=
结束窗口时间(当前记录)+宽限期>观察到的流时间

正如您所描述的,如果多个任务并行运行以基于分组键洗牌消息,并且某些任务比其他任务慢(或者某些分区处于脱机状态),这将创建无序消息。不幸的是,我担心解决这个问题的唯一办法是增加
宽限期

这实际上是可用性和一致性之间的永恒权衡

[KafkaStream和KafkaStream/KTable连接的行为

使用Kafka Streams执行联接操作时,内部任务将分配给多个共同分区主题上的“同一”分区。例如,任务0将分配给Topic1-Partition0和TopicB-Partition0

获取的记录按分区缓冲到由任务管理的内部队列中。因此,每个队列包含单个分区等待处理的所有记录

然后,从队列中逐个轮询记录,并由拓扑实例进行处理。但是,这是来自非空队列的记录,具有从轮询实例返回的最低时间戳

此外,如果队列为空,则任务可能在一段时间内变为空闲状态,这样就不会从队列轮询更多记录。您可以实际配置任务保持空闲的最长时间,可以使用流配置定义:


此机制允许同步共本地化分区。但是,默认情况下,
max.task.idle.ms
设置为0。这意味着任务永远不会等待来自分区的更多数据,这可能会导致记录被过滤,因为流时间可能会增加得更快。

感谢您的解释。我的问题不是about KStream KStream加入,但关于单个KStream事件时间聚合,之前是流洗牌。我更新了问题以更好地描述此场景。好的,我明白了。我更新了答案,但不幸的是,我认为没有任何解决方案(我仍在思考…)