Structured Streaming和flink都支持流式操作,支持对乱序数据的处理,都引入了watermark的概念,watermark都是系统能处理的乱序数据的最早的时间,但二者的具体表现也不尽相同。
1、Structured Streaming的watermark机制
-
(a+) 在对 event time 做 window() + groupBy().aggregation() 即利用状态做跨执行批次的聚合,并且
-
(b+) 输出模式为 Append 模式或 Update 模式
时,Structured Streaming 将依靠 watermark 机制来限制状态存储的无限增长、并(对 Append 模式)尽早输出不再变更的结果。
如果既不是 Append 也不是 Update 模式,或者是 Append 或 Update 模式、但不需状态做跨执行批次的聚合时,则不需要启用 watermark 机制。
watermark的更新
1)spark任务执行以集群时间为准,window操作处理当前时间段(与event time无关)收到的数据,如图中每隔5min进行一次window操作,window的长度是10min。
2)watermark在每个window操作进行时更新,为当前收到的最大的event time-允许的延迟时间,如:图中12:15的batch,watermark为这期间收到的最大的event time12:14-10=12:04,当前的watermark会在下一次计算时用到。
3)当watermark超过window endtime的时候,认为那个window的数据已经不再变化,会输出计算结果,state store清理那个window的数据,如:图中12:25时,watermark=12:21-10=12:11,此刻认为12:00-12:10的数据已经全部处理了,输出12:00-12:10的计算结果。
2、Flink的watermark机制
1)Fink的时间
Flink的时间分为以下3种:
针对stream数据中的时间,可以分为以下三种:
-
Event Time:事件产生的时间,它通常由事件中的时间戳描述。
-
Ingestion time:事件进入Flink的时间
-
Processing Time:事件被处理时当前系统的时间
2)flink的watermark有两种:
Periodic Watermarks:周期性的(一定时间间隔或者达到一定的记录条数)产生一个Watermark。在实际的生产中Periodic的方式必须结合时间和积累条数两个维度继续周期性产生Watermark,否则在极端情况下会有很大的延时。
Punctuated Watermarks:数据流中每一个递增的EventTime都会产生一个Watermark。在实际的生产中Punctuated方式在TPS很高的场景下会产生大量的Watermark在一定程度上对下游算子造成压力,所以只有在实时性要求非常高的场景才会选择Punctuated的方式进行Watermark的生成。
3)flink的watermark机制:
输入的数据中,根据自身的Event Time,将数据划分到不同的window中,如果window中有数据,则当watermark时间>=Event Time时,就符合了window触发的条件了,但最终决定window触发,还是由数据本身的Event Time所属的window中的window_end_time决定。
a、watermark时间 >= window_end_time
b、在[window_start_time,window_end_time)中有数据存在
在flink里watermark时间会触发window操作的执行。
Flink 提供了 allowedLateness 方法可以实现对迟到的数据设置一个延迟时间, 在指定延迟时间内到达的数据还是可以触发 window 执行的。
第一次触发的条件是watermark时间 >= window_end_time
第二次(或多次)触发的条件是 watermark < window_end_time + allowedLateness 时间内, 这个窗口有 late 数据到达时。如果乱序数据很多,会触发多次window操作。
当watermark >= window_end_time + allowedLateness时,late的数据就不会再处理了