-
背景
-
一般我们都是用EventTime事件时间进行处理统计数据
-
但数据由于网络问题延迟、乱序到达会导致窗口计算数据不准确
-
需求:比如时间窗是 [12:01:01,12:01:10 ) ,但是有数据延迟到达
- 当 12:01:10 秒数据到达的时候,不立刻触发窗口计算
- 而是等一定的时间,等迟到的数据来后再关闭窗口进行计算
-
-
生活中的例子
-
xx公司:每天10点后就是迟到,需要扣工资
-
老王上班 路途遥远(延迟) 经常迟到
- HR就规定迟到5分钟后就罚款100元(5分钟就是watermark)
- 迟到30分钟就是上午事假处理 (5~30分就是 allowLateness )
- 不请假都是要来的 (超过30分钟就是侧输出流,sideOutPut兜底)
-
超过5分钟就不用来了吗?还是要来的继续工作的,不然今天上午工资就没了
-
那如果迟到30分钟呢? 也要来的,不然就容易产生更大的问题,缺勤开除。。。。
-
-
Watermark 水位线介绍
-
由flink的某个operator操作生成后,就在整个程序中随event数据流转
- With Periodic Watermarks(周期生成,可以定义一个最大允许乱序的时间,用的很多)
- With Punctuated Watermarks(标点水位线,根据数据流中某些特殊标记事件来生成,相对少)
-
衡量数据是否乱序的时间,什么时候不用等早之前的数据
-
是一个全局时间戳,不是某一个key下的值
-
是一个特殊字段,单调递增的方式,主要是和数据本身的时间戳做比较
-
用来确定什么时候不再等待更早的数据了,可以触发窗口进行计算,忍耐是有限度的,给迟到的数据一些机会
-
注意
- Watermark 设置太小会影响数据准确性,设置太大会影响数据的实时性,更加会加重Flink作业的负担
- 需要经过测试,和业务相关联,得出一个较合适的值即可
-
-
窗口触发计算的时机
-
watermark之前是按照窗口的关闭时间点计算的 [12:01:01,12:01:10 )
-
watermark之后,触发计算的时机
- 窗口内有数据
- Watermaker >= Window EndTime窗口结束时间
-
触发计算后,其他窗口内数据再到达也被丢弃
-
Watermaker = 当前计算窗口最大的事件时间 - 允许乱序延迟的时间
-
- 数据流中的事件是有序
- 数据流中的事件是无序
案例
-
window大小为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数据,
-
-
Watermaker 计算 = 当前计算窗口最大的事件时间 - 允许乱序延迟的时间
-
什么时候触发W1窗口计算
-
Watermaker >= Window EndTime窗口结束时间
-
当前计算窗口最大的事件时间 - 允许乱序延迟的时间 >= Window EndTime窗口结束时间
-