flink1.12版本开始,事件事件作为默认的时间语义
工厂生产的商品上面印有时间戳,八点到九点的商品要坐一班车运走,商品从生产到运上车中间有一定的时间间隔,班车不能以系统时间作为时间判断标准,而应该以商品上面自带的时间戳作为时间判断标准,八点十分的商品来了,班车认为现在时间到了八点十分,九点钟的商品来了,班车认为现在时间到了九点,那么班车就带着[8,9)的商品出发了 但是这样的话只有当前的班车知道现在时间是多少,后面的班车不知道现在时间(逻辑时间),那么后面的班车就不能进行时间相关的操作 应该有一个标志来指明当前数据流里面时钟到底是怎么样前进的,而且这些标志需要从前边的算子任务传递到后面的算子任务,即使当前窗口数据没有输出,也要把当前时钟的标志传递到下游,下游的任务就不用依赖数据里面的标签了
那么水位线就是用来指明当前逻辑时钟进展的标记 (毫秒数)
问题一:如果数据稀疏,来一个数据判断一下时间戳,插入对应的水位线,没问题 但是如果数据非常稠密,同一毫秒有海量的数据到来,这时候如果还每一条数据都判断时间戳,插入水位线,就做了大量的无用功 解决方法:周期性的生成水位线
问题二:数据是乱序的,比方说八点二十的数据已经到了,八点十分的数据才到,这时候再按照迟到的八点十分的数据生成水位线就倒退了,但是时间一定是单调递增的,时间是不能倒退的 解决方法:判断当前最新的时间戳是否比之前最大的时间戳要大,如果大的话,时间才超前进展,如果小,那就是一个迟到数据,对时间的进展没有贡献 周期性生成水位线,保留之前所有数据中最大时间戳,需要插入水位线的时候,直接以它作为时间戳生成新的水位线
问题三:如何处理迟到数据 解决方法:经验性的给一个延迟时间 两种方案:1.比方说[0-9)秒的窗口,给了2秒的延迟,那么等到11秒水位线生成的时候才发车 2.[0-9)秒的窗口,给了2秒的延迟,最大时间戳为9秒的时候,生成的水位线减两秒,最大时间戳为11秒的时候,生成的水位线减两秒,也就是九秒,刚好发车 两种处理方法是等价的,但是后面一种更好理解,所以我们选择后面一种
设置水位线离源越近越好
允许延迟 .allowedLateness(Time.minutes(1))
侧输出流 OutputTag<> outputTag = new OutputTag<>(“late”){};
.sideOutputLateData(outputTag)
|