1.Time的分类
EvenTime-事件时间:是数据/事件真真正正产生或发生的时间。
IngestionTime-摄入事件:是数据/事件到达流系统的时间。
ProcessingTime-处理时间:是被流系统处理计算时的时间。
问题:上面三个时间,我们更关注于哪个?
答案:更关注于事件时间。
因为事件事件更能反应事件的本质,是数据发生或者产生的时间,该时间是不具有延迟性的。
2.EventTime的重要性
示例1
假设,你正在去往地下停车场的路上,并且打算用手机点一份外卖。选好了外卖后,你就用在线支付功能付款了,这个时候是11点59分。恰好这时,你走进了地下停车库,而这里并没有手机信号。因此外卖的在线支付并没有立刻成功,而支付系统一直在Retry重试“支付”这个操作。
当你找到自己的车并且开出地下停车场的时候,已经是12点01分了。这个时候手机重新有了信号,手机上的支付数据成功发到了外卖在线支付系统,支付完成。
在上面这个场景中你可以看到,
支付数据的事件时间是11点59分,而支付数据的处理时间是12点01分
问题:
如果要统计12之前的订单金额,那么这笔交易是否应被统计?
答案:
应该被统计,因为该数据的真真正正的产生时间为11点59分,即该数据的事件时间为11点59分,
事件时间能够真正反映/代表事件的本质! 所以一般在实际开发中会以事件时间作为计算标准
示例2
一条错误日志的内容为:
2020-11-11 22:59:00 error NullPointExcep --事件时间
进入Flink的时间为2020-11:11 23:00:00 --摄入时间
到达Window的时间为2020-11:11 23:00:10 --处理时间
问题:
对于业务来说,要统计1h内的故障日志个数,哪个时间是最有意义的?
答案:
EventTime事件时间,因为bug真真正正产生的时间就是事件时间,只有事件时间才能真正反映/代表事件的本质!
实际开发中会以事件时间作为计算标准
示例3
某 App 会记录用户的所有点击行为,并回传日志(在网络不好的情况下,先保存在本地,延后回传)。
A用户在 11:01:00 对 App 进行操作,B用户在 11:02:00 操作了 App,
但是A用户的网络不太稳定,回传日志延迟了,导致我们在服务端先接受到B用户的消息,然后再接受到A用户的消息,消息乱序了。
问题:
如果这个是一个根据用户操作先后顺序,进行抢购的业务,那么是A用户成功还是B用户成功?
答案:
应该算A成功,因为A确实比B操作的早,但是实际中考虑到实现难度,可能直接按B成功算
也就是说,实际开发中希望基于事件时间来处理数据,但因为数据可能因为网络延迟等原因,出现了乱序,按照事件时间处理起来有难度!
示例4
在实际环境中,经常会出现,因为网络原因,数据有可能会延迟一会才到达Flink实时处理系统。我们先来设想一下下面这个场景:
原本应该被该窗口计算的数据因为网络延迟等原因晚到了,就有可能丢失了
事件时间计算处理起来有难度!
总结
实际开发中我们希望基于事件时间来处理数据,但因为数据可能因为网络延迟等原因,出现了乱序或延迟到达,那么可能处理的结果不是我们想要的甚至出现数据丢失的情况,
所以需要一种机制/技术来解决一定程度上的数据乱序或延迟到底的问题!
也就是我们接下来要学习的Watermaker水印机制/水位线机制
Watermaker水印机制/水位线机制
什么是watermaker
watermaker就是给数据再额外的加的一个时间列,本质上是一个时间戳。
如何计算watermaker
watermaker = 数据的事件时间 - 最大允许的延迟时间或乱序时间
注意:后面通过源码会发现,准确来说:
watermaker = 当前的最大的事件时间 - 最大允许的延迟时间或乱序时间
这样可以保证watermaker水位线会一直上升(变大),不会下降。
watermaker有什么用
之前的窗口都是按照系统时间来触发计算的,如: [10:00:00 ~ 10:00:10) 的窗口,
一但系统时间到了10:00:10就会触发计算,那么可能会导致延迟到达的数据丢失!
那么现在有了Watermaker,窗口就可以按照Watermaker来触发计算!
也就是说Watermaker是用来触发窗口计算的!
Watermaker如何触发窗口计算的
窗口计算的触发条件为:
- 窗口中有数据
- Watermaker >= 窗口的结束时间
因为前面说到
Watermaker = 当前窗口的最大的事件时间 - 最大允许的延迟时间或乱序时间
也就是说只要不断有数据来,就可以保证Watermaker水位线是会一直上升/变大的,不会下降/减小的
所以最终一定是会触发窗口计算的
注意:
上面的触发公式进行如下变形:
Watermaker >= 窗口的结束时间 -------触发窗口计算条件
Watermaker = 当前窗口的最大的事件时间 - 最大允许的延迟时间或乱序时间 --------计算watermaker
当前窗口的最大的事件时间 - 最大允许的延迟时间或乱序时间 >= 窗口的结束时间
所以窗口的触发时机变成了如下条件:
当前窗口的最大的事件时间 >= 窗口的结束时间 + 最大允许的延迟时间或乱序时间
watermaker的执行过程