提出问题
窗口是按照 flink所在服务器的 系统时间 触发计算的,即:系统时间 到达 窗口结束时间,就会开始计算,会导致 迟到数据丢失
提示:窗口时间是左闭右开,即:包含开始时间、不包含结束时间
如上图:
当
系统时间到达09:21:20,窗口1 开始计算,不会等待迟到的数据3和数据4当
系统时间到达09:21:30,窗口2 开始计算,由于数据3和数据4的事件时间,在 窗口1 范围内,所以 窗口2 计算 不包括数据3和数据4
结论: 由于 数据3 和 数据4 迟到,会被 丢弃
解决
flink 提供 Watermark(水印、水位线)机制,解决上面问题
Watermark 水印、水位线
Watermark 是一个时间戳
作用:窗口 按照 Watermark 触发计算,在 一定程度 上 解决 迟到数据丢失 的问题
计算方式
Watermark = 窗口中的数据的最大事件时间 - 最大允许延迟时间或乱序时间
解释: 最大允许延迟时间或乱序时间 是自定义的
作用: 保证 Watermark 会一直上升(增大),不会下降(减小)
例子
在上面的窗口中,有 2 个数据,其中最大的事件时间是 09:21:15,那么:
Watermark = 09:21:15 - 最大允许延迟时间或乱序时间
例子
又来一个数据,在上面的窗口中,有 3 个数据,其中最大的事件时间是 09:21:15,那么:
Watermark = 09:21:15 - 最大允许延迟时间或乱序时间
触发条件
窗口中有数据
Watermark >= 窗口结束时间
计算公式变换
由于 Watermark = 窗口中的数据的最大事件时间 - 最大允许延迟时间或乱序时间
所以 触发条件变为:窗口中的数据的最大事件时间 - 最大允许延迟时间或乱序时间 >= 窗口结束时间
例子
迟到数据
如下图:数据3、数据4 应该属于 窗口1,但由于迟到,落在 窗口2 中
触发计算
如上图:设置 watermark,最大允许延迟时间或乱序时间是 5 秒,当收到 数据6 时,其事件时间 为 最大事件时间: 09:21:26
根据公式:Watermark = 窗口中的数据的最大事件时间 - 最大允许延迟时间或乱序时间
计算:Watermark = 09:21:26 - 5秒 = 09:21:21
由于 Watermark (09:21:21) 大于等于 窗口1 的结束时间(09:21:19),所以 触发 窗口1 计算,并且 窗口1 包含 迟到的 数据3 和 数据4,类似下图:
理解
窗口结束时间延长了,触发计算的条件,不在由 窗口结束时间 决定,而是是动态的,由 窗口中的数据的最大事件时间 和 最大允许延迟时间或乱序时间 决定
结论
通过 Watermark 触发计算,在一定程度上,避免漏掉迟到数据
缺点
收到 数据5 时,由于 数据5的事件时间 09:21:26 - 延迟 5 秒 >= 窗口结束时间 09:21:20,会触发 窗口1 计算
由于 数据3 迟到太多,仍然会被 丢弃
总结
- Watermark 是一个时间戳
- 计算方法:
Watermark = 窗口中的数据的最大事件时间 - 最大允许延迟时间或乱序时间 - 本质:是让 窗口结束时间延长
- 作用:解决数据乱序、数据延迟
- 缺点:数据延迟太多,会被 漏掉






