【API篇】九、Flink的水位线
文章目录
- 1、Flink时间语义
- 2、事件时间和窗口
- 3、水位线
- 4、水位线和窗口的工作原理
1、Flink时间语义
- 事件时间
- 处理时间
举个例子就是,一条数据在23:59:59产生,在00:00:01被处理,前者为事件时间,后者为处理时间。
从Flink1.12版本开始,Flink已经将事件时间作为默认的时间语义了。
2、事件时间和窗口
逻辑上的时钟,不会像生活中的时钟,时间会自动流逝。08:59:59的数据到了,逻辑时钟才认为时间到了08:59:59,没有数据来,逻辑时钟就不会推进
3、水位线
关于水位线的理解:
- 是一条数据
- 是插入到数据流中的一个标记点,是真实存储的数据
- 内容是一个时间戳,指示了当前的事件时间
有序流中的水位线:
理想状态下,数据量小,且按生成的先后顺序进入流中,此时,可以给每个数据都产生一个水位线:
实际环境下,数据流巨大,且数据涌来的时差极小,此时可每隔一段时间来生成一个水位线:
乱序流中的水位线:
分布式系统下,数据在各个节点之间传输,会因网络延迟等问题而发生顺序改变,产生数据的乱序,如下示意图:
当乱序+数据量小时,可以每来一个数据,先判断其时间戳(水位线)是否比前面数据大,否则就不生成新的水位线。此时,就可以依旧靠数据来推动逻辑时钟前进。
当乱序+数据流大时,可周期性生成水位线,一定长度时间的数据里,最大的时间戳做为水位线:
按照以上的逻辑,会有窗口下的迟到数据,如图中深灰色的数据。有个0-10秒的窗口,乱序数据下,有个10s的数据先到了,如果按正常逻辑,水位线就会被推进到10s的时刻,10s > 10s-1ms ,此时就会触发窗口关闭和输出,但这个输出可能还有迟到的数据未统计到。
针对迟到数据,可以等待一段时间(加延迟),比如2s,即用当前已有数据的最大时间戳减去2秒,当作插入的水位线时间戳,如此,可防止丢数据。
总结:
- 水位线是插入到数据流中的一个标记,可以认为是一个特殊的数据
- 水位线主要的内容是一个时间戳,用来表示当前事件时间的进展
- 水位线是基于数据的时间戳生成的
- 水位线的时间戳必须单调递增,以确保任务的事件时间时钟一直向前推进
- 水位线可以通过设置延迟,来保证正确处理乱序数据个
- 水位线Watermark(t),表示在当前流中事件时间已经达到了时间戳t,这代表t之前的所有数据都到齐了,之后流中不会出现时间截t’< = t 的数据
4、水位线和窗口的工作原理
窗口可理解成一个桶,但这个装水的桶不是反复用的,不是说接完水后倒掉继续接下一桶,这是错误理解。如果按照这样理解,加了延迟时间后,岂不是会把后面桶里的数据给误倒掉。实际底层不是这样的,加了延迟时间以后,只是对前一个桶触发计算和关闭的时间延后了。像图中的11和12这两条数据(橙色),该是第二个桶的还是会去第二个桶,每个窗口都是一个个独立的桶,每个数据都会分发到对应的桶中,当到达窗口结束时间时,对每个桶中收集的数据进行计算处理。
往后继续也是一样:
Flink中窗口并不是静态准备好的,而是动态创建——当有落在这个窗口区间范围的数据达到时,才创建对应的窗口
另外,这里我们认为到达窗口结束时间时,窗口就触发计算并关闭,事实上“触发计算”和“窗口关闭”两个行为也可以分开。