watermark Apache Flink为了处理EventTime 窗口计算提出的一种机制,本质上也是一种时间戳,
由Apache Flink Source或者自定义的Watermark生成器按照需求Punctuated或者Periodic两种方式生成的一种系统Event,
与普通数据流Event一样流转到对应的下游算子,接收到Watermark Event的算子以此不断调整自己管理的EventTime clock。
算子接收到一个Watermark时候,框架知道不会再有任何小于该Watermark的时间戳的数据元素到来了,所以Watermark可以看做是告诉Apache Flink框架数据流已经处理到什么位置(时间维度)的方式。
通常基于Event Time的数据,自身都包含一个timestamp.watermark是用于处理乱序事件的,而正确的处理乱序事件,通常用watermark机制结合window来实现。
waterMark 的触发时间机制(waterMark >= window_end_time)
当第一次触发之后,以后所有到达的该窗口的数据(迟到数据)都会触发该窗口
定义允许延迟,所以 waterMark<window_end_time+allowedLateness 的这段时间内,有数据落入窗口也会触发计算,当
waterMark>=window_end_time+allowedLateness 是窗口被关闭,数据被丢弃
对于out-of-order的数据,Flink可以通过watermark机制结合window的操作,来处理一定范围内的乱序数据,(新进来的数据)晚于前面进来的数据,但是该数据所在窗口没有被触发,
这个时候数据还是有效的——EventTime<WaterMark 的
对于out-of-order的数据,延迟太多
注意,如果不定义允许最大迟到时间,并且在有很多数据迟到的情况下,会严重影响正确结果,只要Event Time < watermark时间就会触发窗口,也就是说迟到的每一条数据都会触发
该窗口
Punctuated
数据流中每一个递增的EventTime都会产生一个Watermark(其实是根据某个计算条件来做判断)。
在实际的生产中Punctuated方式在TPS很高的场景下会产生大量的Watermark在一定程度上对下游算子造成压力,所以只有在实时性要求非常高的场景才会选择Punctuated的方式进行Watermark的生成。
每个事件都会携带事件,可以根据该时间产生一个watermark 或者可以根据事件携带的其他标志——业务的结束标志
Periodic - 周期性的(一定时间间隔或者达到一定的记录条数)产生一个Watermark。
在实际的生产中Periodic的方式必须结合时间和积累条数两个维度继续周期性产生Watermark,否则在极端情况下会有很大的延时。 背景流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的。虽然大部分情况下,流到operator的数据都是按照事件产生的时间顺序来的
但是也不排除由于网络、背压等原因,导致乱序的产生(out-of-order或者说late element)。
对于late element,我们又不能无限期的等下去,必须要有个机制来保证一个特定的时间后,必须触发window去进行计算了
它表示当达到watermark到达之后,在watermark之前的数据已经全部达到(即使后面还有延迟的数据
解决的问题Watermark的时间戳可以和Event中的EventTime 一致,也可以自己定义任何合理的逻辑使得Watermark的时间戳不等于Event中的EventTime,
Event中的EventTime自产生那一刻起就不可以改变了,不受Apache Flink框架控制,
而Watermark的产生是在Apache Flink的Source节点或实现的Watermark生成器计算产生(如上Apache Flink内置的 Periodic Watermark实现),
Apache Flink内部对单流或多流的场景有统一的Watermark处理。
默认情况下小于watermark 时间戳的event 会被丢弃吗
多流waterMark在实际的流计算中往往一个job中会处理多个Source的数据,对Source的数据进行GroupBy分组,那么来自不同Source的相同key值会shuffle到同一个处理节点,
并携带各自的Watermark,Apache Flink内部要保证Watermark要保持单调递增,多个Source的Watermark汇聚到一起时候可能不是单调自增的
Apache Flink内部实现每一个边上只能有一个递增的Watermark, 当出现多流携带Eventtime汇聚到一起(GroupBy or Union)时候,
Apache Flink会选择所有流入的Eventtime中最小的一个向下游流出。从而保证watermark的单调递增和保证数据的完整性
默认情况下watermark 已经触发过得窗口,即使有新数据(迟到)落进去不会被计算 ,迟到的意思
watermark>=window_n_end_time && window_n_start_time<=vent_time<window_n_end_time(即数据属于这个窗口)