Apache kafka FlinkKafkaConsumer中事件时间顺序的保证

Apache kafka FlinkKafkaConsumer中事件时间顺序的保证,apache-kafka,apache-flink,flink-streaming,stream-processing,Apache Kafka,Apache Flink,Flink Streaming,Stream Processing,TL;DR:目前保证Flink中事件时间顺序的最佳解决方案是什么 我将Flink 1.8.0与卡夫卡2.2.1结合使用。我需要通过事件时间戳来保证事件的正确顺序。我每隔1s生成周期性水印。我将FlinkKafkaConsumer与AscendingTimestampExtractor一起使用: val rawConsumer=new FlinkKafkaConsumer[T]主题名,反序列化模式,kafkaConsumerConfig .AssignTimestamp和Watermarks新上升

TL;DR:目前保证Flink中事件时间顺序的最佳解决方案是什么

我将Flink 1.8.0与卡夫卡2.2.1结合使用。我需要通过事件时间戳来保证事件的正确顺序。我每隔1s生成周期性水印。我将FlinkKafkaConsumer与AscendingTimestampExtractor一起使用:

val rawConsumer=new FlinkKafkaConsumer[T]主题名,反序列化模式,kafkaConsumerConfig .AssignTimestamp和Watermarks新上升时间提取程序[T]{ 覆盖def Extraction AscendingTimeStampElement:T:Long= 萃取元素 } .addSourceconsumerdeserializationSchema.getProducedType.uidsourceId.namesourceId 然后处理:

myStream .keyByev=>ev.name,ev.group .mapWithState[ResultEvent,ResultEvent]DefaultCalculator.calculateResultEventState 我意识到,对于在同一毫秒或几毫秒之后发生的无序事件,Flink不会纠正顺序。我在文档中发现:

水印触发所有窗口的计算,其中最大时间戳(即结束时间戳-1)小于新水印

因此,我准备了额外的处理步骤,以保证事件的时间顺序:

myStream .timeWindowAllTime.毫秒100 .applywindow,输入,输出:收集器[MyEvent]=>input .toList.sortBy_u2;getTimestamp .foreachout.collect//此窗口按事件时间保证正确的顺序 [MyEvent]类的类型信息 .keyByev=>ev.name,ev.group .mapWithState[ResultEvent,ResultEvent]DefaultScoring.calculateResultEventState 然而,我发现这个解决方案很难看,看起来像是一个解决办法。我也担心


理想情况下,我希望将顺序保证放在KafkaSource中,并为每个kafka分区保留它,就像每个分区的水印一样。有可能吗?目前保证Flink事件时间顺序的最佳解决方案是什么?

这是一个很好的观点。卡夫卡索资源中的秩序保障实际上包括两部分

保证同一子任务中分区之间的顺序。 保证子任务之间的顺序。 第一部分已经在进行中。第二部分需要子任务之间共享状态的支持,这可能需要社区中更多的讨论和详细的计划


回到你的问题,我认为通过设置缓冲数据的窗口来保持事件的顺序是目前最好的解决方案。

这是一个很好的观点。卡夫卡索资源中的秩序保障实际上包括两部分

保证同一子任务中分区之间的顺序。 保证子任务之间的顺序。 第一部分已经在进行中。第二部分需要子任务之间共享状态的支持,这可能需要社区中更多的讨论和详细的计划


回到你的问题,我认为通过设置缓冲数据的窗口来保持事件的顺序是目前最好的解决方案。

Flink不能保证按照事件时间顺序处理记录。分区内的记录将按其原始顺序进行处理,但当两个或多个分区由于流的重新分区或合并而合并到一个新分区中时,Flink会将这些分区的记录随机合并到新分区中。其他一切都将是低效的,并导致更高的延迟

例如,如果您的作业有一个从两个Kafka分区读取的源任务,那么两个分区的记录将以某种随机的之字形模式合并

但是,Flink保证所有事件都能正确处理生成的水印。这意味着,水印永远不会超过记录。例如,如果Kafka源生成每个分区的水印,则即使合并了多个分区的记录,这些水印仍然有效。水印用于收集和处理时间戳小于水印的所有记录。因此,它确保了输入数据的完整性

这是按时间戳对记录进行排序的先决条件。你可以用一个翻滚的窗户来做这一切。但是,您应该知道

所有窗口都将在单个任务中执行,即,它不是并行的。如果每个键的顺序足够,您应该使用常规的翻滚窗口,或者更好地实现KeyedProcessFunction,这样效率更高。 由于重新分区或更改并行性而重新组织流时,顺序将被破坏。
Flink不保证按事件时间顺序处理记录。分区内的记录将按其原始顺序进行处理,但当两个或多个分区由于流的重新分区或合并而合并到一个新分区中时,Flink会将这些分区的记录随机合并到新分区中。其他一切都将是低效的,并导致更高的延迟

< p> 例如,如果您的作业有一个从两个Kafka分区读取的源任务,那么两个分区的记录将以某种随机的之字形模式合并

但是,Flink保证所有事件都能正确处理生成的水印。这意味着,水印永远不会超过记录。例如,如果Kafka源生成每个分区的水印,则即使合并了多个分区的记录,这些水印仍然有效。水印用于收集和处理时间戳小于水印的所有记录。因此,它确保了输入数据的完整性

这是按时间戳对记录进行排序的先决条件。你可以用一个翻滚的窗户来做这一切。但是,您应该知道

所有窗口都将在单个任务中执行,即,它不是并行的。如果每个键的顺序足够,您应该使用常规的翻滚窗口,或者更好地实现KeyedProcessFunction,这样效率更高。 由于重新分区或更改并行性而重新组织流时,顺序将被破坏。