在使用 EventTime 处理 Stream 数据的时候会遇到数据乱序的问题,流处理从 Event(事 件)产生,流经 Source,再到 Operator,这中间需要一定的时间。虽然大部分情况下,传 输到 Operator 的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络延迟等原因而导致乱序的产生,特别是使用 Kafka 的时候,多个分区之间的数据无法保证有序。因此, 在进行 Window 计算的时候,不能无限期地等下去,必须要有个机制来保证在特定的时间后, 必须触发 Window 进行计算,这个特别的机制就是 Watermark(水位线)。Watermark 是用于 处理乱序事件的。

1.Watermark 原理

在 Flink 的窗口处理过程中,如果确定全部数据到达,就可以对 Window 的所有数据做 窗口计算操作(如汇总、分组等),如果数据没有全部到达,则继续等待该窗口中的数据全 部到达才开始处理。这种情况下就需要用到水位线(WaterMarks)机制,它能够衡量数据处 理进度(表达数据到达的完整性),保证事件数据(全部)到达 Flink 系统,或者在乱序及 延迟到达时,也能够像预期一样计算出正确并且连续的结果。当任何 Event 进入到 Flink 系统时,会根据当前最大事件时间产生 Watermarks 时间戳。

那么 Flink 是怎么计算 Watermak 的值呢?

Watermark = 进入 Flink 的最大的事件时间(mxtEventTime)— 指定的延迟时间(t)

那么有 Watermark 的 Window 是怎么触发窗口函数的呢?

如果有窗口的停止时间等于或者小于 maxEventTime – t(当时的 warkmark),那么 这个窗口被触发执行。

注意:Watermark 本质可以理解成一个延迟触发机制。

Watermark 的使用存在三种情况:

  1. 本来有序的 Stream 中的 Watermark
    如果数据元素的事件时间是有序的,Watermark 时间戳会随着数据元素的事件时间按顺 序生成,此时水位线的变化和事件时间保持一致(因为既然是有序的时间,就不需要设置延 迟了,那么 t 就是 0。所以 watermark=maxtime-0 = maxtime),也就是理想状态下的水位 线。当 Watermark 时间大于 Windows 结束时间就会触发对 Windows 的数据计算,以此类推, 下一个 Window 也是一样。
    Flink的Time详解之Watermark原理_kafka
  2. 乱序事件中的 Watermark
    现实情况下数据元素往往并不是按照其产生顺序接入到 Flink 系统中进行处理,而频繁 出现乱序或迟到的情况,这种情况就需要使用 Watermarks 来应对。比如下图,设置延迟时 间 t 为
    Flink的Time详解之Watermark原理_数据_02
  3. 并行数据流中的 Watermark
    在多并行度的情况下,Watermark 会有一个对齐机制,这个对齐机制会取所有 Channel 中最小的 Watermark。
    Flink的Time详解之Watermark原理_flink_03