02-Flink 迟到事件
Flink 的 Watermark(水位线)(括号里说出来就是真正用过的而不是光背答案)★★★★
Watermark 是 Flink 处理乱序事件的机制,基于事件时间,通常用来触发窗口计算。Watermark 是 EventTime 下使用 处理进度的标志,仅限于 EventTime 下使用。
在使用 EventTime 处理 Stream 数据的时候会遇到数据乱序的问题,流处理从 Event(事件)产生,流经 Source,再到 Operator,这中间需要一定的时间。虽然大部分情况下,传输到 Operator 的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络延迟等原因而导致乱序的产生,特别是使用 Kafka 的时候,多个分区之间的数据无法保证有序。
因此,在进行 Window 计算的时候,不能无限期地等下去,必须要有个机制来保证在特定的时间后触发 Window 进行计算,这个特别的机制就是 Watermark。Watermark 是用于处理乱序事件的。
在 Flink 的窗口处理过程中,如果确定全部数据到达,就可以对 Window 的所有数据做窗口计算操作(如汇总、分组等),如果数据没有全部到达,则继续等待该窗口中的数据全部到达才开始处理。这种情况下就需要用到水位线(WaterMarks)机制,它能够衡量数据处理进度(表达数据到达的完整性),保证事件数据(全部)到达 Flink 系统,或者在乱序及延迟到达时,也能够像预期一样计算出正确并且连续的结果。
Watermark 可以理解一个特殊的数据,插入到流里面。
Watermark 也可以表示为 Watermaker = 当前计算窗口最大的事件时间 - 允许乱序延迟时间
示例:
windows 大小为 10s,窗口:
W1[23:12:00~23:12:10],W2[23:12:10~23:12:20]
event time:
数据A 23:12:07
数据B 23:12:11
数据C 23:12:08
数据D 23:12:17
数据E 23:12:09
没加入 Watermark,由上到下进入 Flink
- 数据B 到了之后,W1 就进行了窗口计算,只有 数据A
- 数据C 迟到了3秒到了之后,由于 W1 已经计算了,所以就丢失了 数据C
加入 Watermark,允许 5 秒乱序延迟,由上到下进入 Flink
- 数据A 到达:
watermark = 12:07 - 5 = 12:02 < 12:10
,所以不触发 W1 计算,数据A 属于 W1 - 数据B 到达:
watermark = max{12:11, 12:07} - 5 =12:06 < 12:10
,所以不触发 W1 计算,数据B 属于 W2 - 数据C 到达:
watermark = max{12:08, 12:11, 12:07} - 5 = 12:06 <12:10
,所以不触发 W1 计算,数据C 属于 W1 - 数据D 到达:
watermark = max{12:17, 12:08, 12:11, 12:07} - 5 = 12:12 > 23:12:10
,触发 W1 计算,数据D 属于 W2 - 数据E 到达:
watermark = max{12:09,12:17,12:08,12:11,12:07} -5 =12:12 > 23:12:10
,之前已经触发了 W1 计算,所以丢失了 数据E
- 数据A 到达:
Watermark 注意事项
- Watermark 设置太小,影响数据准确性。
- Watermark 设置太大,影响数据实时性。
迟到事件
虽说水位线表明着早于它的事件不应该再出现,但接收到水位线以前的的消息是不可避免的,这就是所谓的迟到事件。
实际上迟到事件是乱序事件的特例,和一般乱序事件不同的是它们的乱序程度超出了水位线的预计,导致窗口在它们到达之前已经关闭。
迟到事件出现时窗口已经关闭并产出了计算结果,因此处理的方法有 3 种:
- 重新激活已经关闭的窗口并重新计算以修正结果。
- 将迟到事件收集起来另外处理。
- 将迟到事件视为错误消息并丢弃。
Flink 默认的处理方式是第 3 种直接丢弃,其他两种方式分别使用 Side Output 和 Allowed Lateness。
- Side Output 机制可以将延迟事件单独放入一个数据流分支,这会作为 Window 计算结果的副产品,以便用户获取并对其进行特殊处理。
- Allowed Lateness 机制允许用户设置一个允许的最大迟到时长。
Flink 会再窗口关闭后一直保存窗口的状态直至超过允许迟到时长,这期间的迟到事件不会被丢弃,而是默认会触发窗口重新计算。
因为保存窗口状态需要额外内存,并且如果窗口计算使用了 ProcessWindowFunction API 还可能使得每个迟到事件触发一次窗口的全量计算,代价比较大,所以允许迟到时长不宜设得太长,迟到事件也不宜过多,否则应该考虑降低水位线提高的速度或者调整算法。