如何将 Flink streaming timeWindow 与时间戳和水印分配器一起使用?

How to use Flink streaming timeWindow with timestamp and watermark assigners?

我正在研究从 Kafka 读取事件的 Flink 流处理器。这些事件由其中一个字段键入,并且在减少和输出之前应该在一段时间内窗口化。我的处理器使用事件时间作为时间特征,因此从它消耗的事件中读取时间戳。这是它目前的样子:

source
    .map(new MapEvent())
    .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Event>(Time.seconds(10)) {
        @Override public long extractTimestamp(Event event) {
                return event.getTimestamp();
            }
        })
    .keyBy(new KeySelector())
    .timeWindow(Time.minutes(1))
    .reduce(new EventReducer())
    .map(new MapToResult());

我对事件的了解如下:

  1. 他们的活动时间是无序的。
  2. 迟到是可能的,因此事件可能比时间戳显示的要晚得多。为了便于使用,假设我知道,最晚可能到达时间为 20 秒。
  3. 我希望在 Flink 将它们转发到以下 reduce 运算符之前,将我的活动窗口化整整一分钟。

最后,这是我的问题:

  1. 鉴于我之前描述的用例,BoundedOutOfOrdernessTimestampExtractor 是一个不错的选择吗?我已经通读了文档,看到了 AssignerWithPunctuatedWatermarks 和其他可用于水印创建的预定义分配器,但不完全理解,如果这些对我来说更好的话。
  2. assignTimestampsAndWatermarks()如何与timeWindow()方法配合使用?当涉及到迟到时,他们可以干预吗?有什么我必须记住的地方吗?

我觉得应该从水印的概念说起。简而言之,水印表示大多数具有较早时间戳的事件已经到达。基于该假设,当水印通过 window 的末尾时,timeWindow 可以发出 window。当然,仍然可能会发生迟到的情况,这可能需要处理。这里出现了 allowedLateness 的概念,它指定在发出 window 后多长时间我们应该跟踪那里的元素,以便我们可以例如用那些迟到的事件更新我们的接收器(但必须记住window 已在没有此元素的情况下发出)。希望这能以某种方式回答你的第二个问题。

回到你的第一个问题,如果你有很多事件可以延迟 20 秒,我认为 BoundedOutOfOrdernessTimestampExtractor 是最好的选择。这样虽然每 window 发射一次都会延迟那 20 秒。如果迟到是零星的,并且您可以处理重复的,那么您可以考虑另一个。

你提到的 AssignerWithPunctuatedWatermarks,正如文档所说,应该使用以防你的流中的某些特定事件已经充当水印。所以不要认为它适合你 use-case.

有关水印的更多信息,您可以阅读这篇文章doc or this and that

也许你的水印总是小于window-结束时间,这样它就不会触发window yield results.Points如何触发window 如下:

  1. 水印>=window-结束时间。
  2. 这个 window 中有一些元素。