Flink中watermark的生成规则及其功能
问题分析
假如我们自己写一个流式框架。我们该如何处理消息。正常情况下,我们看到消息按照顺序一个个发送,接受后按照顺序处理,这是没有什么问题的。然而也要考虑到一些特殊情况下,消息不在是按照顺序发送,产生了乱序,这时候该怎么处理?
核心问题讲解
(1)watermark是用于处理乱序事件的,而正确的处理乱序事件,通常用watermark机制结合window来实现。我们知道,流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的。虽然大部分情况下,流到operator的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络、背压等原因,导致乱序的产生(out-of-order或者说late element)。但是对于late element,我们又不能无限期的等下去,必须要有个机制来保证一个特定的时间后,必须触发window去进行计算。这个特别的机制,就是watermark。
(2)通常,在接收到source的数据后,应该立刻生成watermark;但是,也可以在接收source后,应用简单的map或者filter操作,然后再生成watermark。
(3)如果延迟的数据有业务需要,则设置好允许延迟的时间,因为我们不能无限期的等下去。每个窗口都有属于自己的最大等待延迟数据的时间限制,窗口结束时间+延迟时间=最大waterMark值,即当waterMark值大于的上述计算出的最大waterMark值,该窗口内的数据就属于迟到的数据,无法参与window计算。
问题扩展
- Window:Window是处理无界流的关键,Windows将流拆分为一个个有限大小的buckets,可以在每一个buckets中进行计算。
- start_time,end_time:当Window时时间窗口的时候,每个window都会有一个开始时间和结束时间(前开后闭),这个时间是系统时间。
- event-time: 事件发生时间,是事件发生所在设备的当地时间,比如一个点击事件的时间发生时间,是用户点击操作所在的手机或电脑的时间。
- Watermarks:可以把他理解为一个水位线,这个Watermarks在不断的变化,一旦Watermarks大于了某个window的end_time,就会触发此window的计算,Watermarks就是用来触发window计算的。
结合项目中使用
watermark如何处理乱序数据?
假如我们设置10s的时间窗口(window),那么0~10s,10~20s都是一个窗口,以0~10s为例,0位start-time,10为end-time。假如有4个数据的event-time分别是8(A),12.5(B),9(C),13.5(D),我们设置Watermarks为当前所有到达数据event-time的最大值减去延迟值3.5秒。
当A到达的时候,Watermarks为max{8}-3.5=8-3.5 = 4.5 < 10,不会触发计算;
当B到达的时候,Watermarks为max(12.5,8)-3.5=12.5-3.5 = 9 < 10,不会触发计算;
当C到达的时候,Watermarks为max(12.5,8,9)-3.5=12.5-3.5 = 9 < 10,不会触发计算;
当D到达的时候,Watermarks为max(13.5,12.5,8,9)-3.5=13.5-3.5 = 10 = 10,触发计算;
触发计算的时候,会将AC(因为他们都小于10)都计算进去。
通过上面这种方式,我们就将迟到的C计算进去了。这里的延迟3.5s是我们假设一个数据到达的时候,比他早3.5s的数据肯定也都到达了,这个是需要根据经验推算的,加入D到达以后有到达了一个E,event-time=6,但是由于0~10的时间窗口已经开始计算了,所以E就丢了。