Flink的Watermark水位线详解
一、Flink的时间语义
Flink有如下三种时间语义: Flink的三种时间语义-CSDN博客
在实际应用中,一般会采用事件时间语义。而正如前面所说的,事件时间语义需要等窗口的数据全部到齐了,才能进行窗口计算。那么,什么时候数据就都到齐了呢?这里我们引入水位线的概念。
二、为什么要引入水位线?不能用数据本身带有的时间戳来驱动吗?
如果用数据本身所带有的时间戳来进行驱动,将会面临如下问题:
(1)如果面临聚合计算,数据本身所带有时间戳也会参与聚合,则聚合之后一批数据只会输出一个结果,那么下游的数据量就会变少,进而影响时间进度控制的精细程度。
(2)数据由上游节点发往下游节点时,往往一个数据只会发往下游的一个节点(除广播外),那么不同并行子任务之间的时钟推进程度就会产生差别,从而影响计算结果。
综上所述,我们需要将将单独的时间信息以数据的形式广播到下游的每一个并行子任务上,并且这个时钟的传递不会因为窗口的聚合计算而受到影响。解决方法就是在数据流中加入一个时钟标记:水位线。
三、水位线概念
水位线可以看作一条特殊的数据记录,它是插入到数据流中的一个数据标识,主要内容就是一个时间戳,用来指示当前流的事件时间。它插入流中的位置,应当是某个数据到来之后,这样就可以从这个数据中提取时间戳,作为当前水位线的时间戳了。如果下游出现了多个并行子任务,应当将水位线广播出去。
四、有序流中的水位线
在理想情况下,数据按照生成的先后顺序依次进入数据流,在处理过程中也会保持原顺序不变。在这种情况下,从每个数据中提取的时间戳一定是单调不减的,在海量数据的情况下,可能有很多数据具有相同的时间戳,那么每个数据的到来都提取时间戳、生成水位线就做了大量的无用功,即使时间戳不同,连续数据的时间戳相隔也会非常之细微,往往对计算结果没什么影响。所以为了提高效率,一般会周期性(如每隔100ms,这里的间隔时间是系统时间)生成水位线。
五、乱序流中的水位线
在分布式系统中,数据往往是乱序的,这种情况下由于存在迟到数据,可能出现水位线回退,因此在插入新的水位线时,要先判断一下时间戳是否比之前的大,否则不再生成新的水位线。此外,考虑到大量数据同时到来时的处理效率,也可以周期性生成水位线,只需要保存之前所有数据中最大的时间戳即可,在需要生成水位线时直接以最大时间戳作为新的水位线。最后,为了等待当前窗口的迟到数据,我们应该为水位线设置一个延迟时间,即把(最大时间戳-延迟时间)作为当前水位线。
六、水位线的特性总结
(1)水位线是插入到数据流中的一个标记,可以认为是一个特殊的数据
(2)水位线的主要内容是一个时间戳,用来表示当前事件时间的进展
(3)水位线是基于数据的时间戳生成的
(4)水位线的时间戳是单调递增的,以确保任务的事件时间时钟一直向前推进
(5)水位线可以通过设置延迟,来确保正确处理乱序数据
(6)一个水位线WaterMark(t),代表在当前流中事件时间已经来到了t,这表示t之前的数据都已经到齐了。
七、水位线的传递
在重分区的传递模式下,下游子任务会收到多个上游子任务广播来的水位线,那么应该以哪个为准呢?回忆水位线的本质:当前时间之前的所有数据都已到齐!那么应当选取最小的水位线作为当前子任务的水位线。
八、水位线总结
(1) 水位线默认默认计算公式:水位线 = 观察到的最大时间戳-延迟时间-1ms
(2) 在数据流开始之前会插入一个负无穷大的水位线,在数据流结束时会插入一个正无穷大的水位线,保证所有的窗口闭合及所有的额定时器被触发。对于离线数据集,只需这两个水位线即可。
原文地址:https://blog.csdn.net/lx104921/article/details/144702314
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!