watermark介绍
在Flink中,Watermark 是 Apache Flink 为了处理 EventTime 窗口计算提出的一种机制, 本质上是一种时间戳。 用来处理实时数据中的乱序问题的,通常是水位线和窗口结合使用来实现。
从设备生成实时流事件,到Flink的source,再到多个oparator处理数据,过程中会受到网络延迟、背压等多种因素影响造成数据乱序。在进行窗口处理时,不可能无限期的等待延迟数据到达,当到达特定watermark时,认为在watermark之前的数据已经全部达到(即使后面还有延迟的数据), 可以触发窗口计算,这个机制就是 Watermark(水位线)。
如上图:
● w(11): 表示11之前的数据到已经到达,11之前的数据可以进行计算了。
● w(20): 表示20之前的数据到已经到达,20之前的数据可以进行计算了。
watermark的使用
生成时机
watermark可以在接收到DataSource的数据后,立刻生成Watermark。也可以在DataSource后,使用map或者filter操作后再生成watermark。
水位线生产的最佳位置是在尽可能靠近数据源的地方,因为水位线生成时会做出一些有关元素顺序相对时间戳的假设。由于数据源读取过程是并行的,一切引起Flink跨行数据流分区进行重新分发的操作(比如:改变并行度,keyby等)都会导致元素时间戳乱序。但是如果是某些初始化的filter、map等不会引起元素重新分发的操作,所以是可以考虑在生成水位线之前使用。
watermark的计算
watermark = 进入 Flink 窗口的最大的事件时间(maxEventTime) — 指定的延迟时间(t)
生成方式
第一种:With Periodic Watermarks
这个是周期性触发Waterrmark的生成和发送。
周期性分配水位线在程序中会比较常用,是我们会指示系统以固定的时间间隔发出的水位线。
在设置时间为事件时间时,会默认设置这个时间间隔为200ms, 如果需要调整可以自行设置。
设置任务时间类型和
val env = StreamExecutionEnvironment.getExecutionEnvironment
//设置时间使用事件时间
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
//设置并行度为1
env.setParallelism(1)
//设置自动周期性的产生watermark,默认值为2