Flink 水位线(Watermark)个人总结

一、水位线定义

        在Flink中,用于衡量事件时间进展的标记,被称为水位线。

        可以看作一条特殊的数据记录,它是插入到数据流中的一个标记点。主要内容就是一个时间戳,用来指示当前的事件时间

        自身理解:本质上就是一个时间戳,表示比这个时间早的事件已经全部到达。并且在数据乱序的情况下,通过水位线可以判断出迟到的数据

1)有序流中的水位线

        1.1 理想状态(数据量比较小),数据按生成的先后顺序进入流中,每条数据产生一个水位线

a14be60d597a4ce5b98e41faf1d8968e.png

        1.2 实际应用中,数据量如果非常大,可能同一时间又很多条数据或者相差非常小的时间间隔(几ms),为了提高效率,一般会每隔一段时间生成一个水位线

1e7898aba0b94e168df65b3d13f9fa82.png

2)乱序流中的水位线

        因为分布式系统中,数据节点传输,可能由于网络延迟,导致事件时间在后面的数据先发送过来,导致顺序改变

293f177731df488ea8bb0e894c4cd934.png

        图中 第7s的数据在第9s后收到

解决办法

        ①:乱序+数据量比较小

        判断一下时间戳是否比之前的大,否则就不再生成新的水位线。如图中第7s的数据来了后发现水位线为9s,这时不更新水位线,知道收到9s之后的数据再更新

28c79a68b59845cbb776ae620e34be6c.png

        ②:乱序+数据量大

        这时只需要保存一下之前所有数据中最大的时间戳,需要插入水位线时,直接用它作为新的水位线

59e4696026fe46c48ea07bf27ec76df4.png

        ③:乱序+迟到数据

        为了能让窗口正确收集到迟到的数据,我们可以等一段时间,比如2s;也就是用当前已有最大数据的时间戳减2s,就是要插入水位线的时间戳

d0dcb9f3c0ae4cb0bcefdba3e87f847d.png

3) 水位线的特性

        ·水位线是插入到数据流中的一个标记,可以认为是一个特殊的数据

        ·水位线主要内容是一个时间戳,用来表示当前事件时间的进展

        ·水位线是基于数据的时间戳生成的

        ·水位线的时间戳必须单调递增,以确保任务的事件事件时钟是一直向前推进的

        ·水位线可以通过设置延迟,来确保正确处理乱序的数据

4)水位线和窗口的工作原理

        窗口可以看作一个个独立的桶,水位线就是一个标记数据流的时间戳。比如watermark标记为10s,在处理乱序的数据时可以设置一个延迟,比如说2s。这时,第12s的数据会放在区间为10~20的窗口中,对于水位线,会划分到第一个区间中。达到水位线之后,前一个窗口关闭触发计算

80848b37ac2246bba35bede655088c6d.png

二、生成水位线

2.1 总体原则

        完美的水位线表示这个时间之前的数据已经全部到齐、之后不会再出现。但是如果保证绝对正确,就必须等待足够长的时间,这样会有更多的延迟

        如果希望处理的更快、实时性更强,那么可以将水位线设置的低一些。但是可能会导致窗口遗漏数据,计算结果不准确

2.2 水位线生成策略

        flink的DataStreamAPI中,assignTimestampAndWatermarks(),用于为流中数据分配时间戳,并生成水位线指示事件时间。

        通过此方法,传入WatermarkStrategy参数,是一个接口,负责从流中的数据提取时间戳,另一个是基于时间戳设置水位线

        1. 定义watermark策略 -> 指定是否有序(<WaterSensor>forMonotonousTimestamps() / <WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(3)))

2.3 Flink内置水位线

        1)有序流内置水位线设置

        主要特点就是时间戳单调增长,永远不会出现事件迟到的问题,直接调用WatermarkStrategy.forMonotonousTimestamps()就可以实现

flink从数据中提取事件时间,每条数据来的时候会带着这个时间作为事件时间。当这个时间超出了水位线,前一个窗口关闭,触发计算

43b287dd7fab4df1b00128b75540c4f2.png

        2)乱序流中内置水位线设置

        需要等待,延迟触发,调用WatermarkStrategy. forBoundedOutOfOrderness()方法

6eb2224b31a44324b239313011f1707a.png

2.4 查看乱序数据流水位线源码

乱序:

3dc2f09f896a48b09b02276392f25148.png7f15505b264649bb9c2b9f5c3be6c88c.png

默认的当前最大事件为Long的最小值+传入的延迟事件

onPeriodicEmit:周期性的发射watermark,默认200ms。

升序:       000b639cb88b4d9cbf57ce32f9ad152b.png

内置的水位线都是周期生成的,默认是200ms。

有序流:watermark = 当前最大的事件时间 - 1ms

乱序流:watermark = 当前最大的事件时间 - 延迟时间 - 1ms

2.5 水位线的传递

        多并行度,对于一个子任务,上游多个往它这边发送数据,可能它们的水位线进展不一样。对于一个task收到多个watermark,这时以最小的watermark作为基准。因为最小的大家肯定都处理过

        ps: 水位线设置空闲等待

        在多个上游并行任务中,如果其中一个没有数据,由于当前task是以最小的那个作为当前任务的事件时钟,就会导致当前task水位线无法推进,就可能导致窗口无法触发。(并行度为2,延迟等待时间为2s,窗口大小为10s,7s,10s,13s,仍然不会触发窗口,因为此时最小并行度为10 - 2 = 8)这时可以设置空闲等待时间

2.6 迟到数据的处理

迟到数据:事件时间小于watermark。 可能会有迟到数据无法进入窗口(因为窗口已关闭,触发计算)

2.6.1 推进水印延迟

        推迟系统时间的推进,设置一个延迟时间,保证窗口计算被延迟执行,为后续乱序的数据争取时间进入窗口。通过定义watermark策略中,设置乱序等待时间,有一个Duration

        在watermark中指定乱序等待的时间

        当前数据最大的事件时间 - 延迟时间 大于水位线了,窗口关闭,触发计算

86babf48e71a42c688e513346bb72e24.png

2.6.2 设置窗口延迟关闭

        通过.window().allowedLateness()设置推迟窗口关闭时间。当触发了窗口计算时,会先计算当前结果,但是此时不会关闭窗口。

        以后每来一条数据,就触发一次窗口增量计算,知道watermark超过了窗口结束时间+推迟时间,然后关闭窗口

        eg:当前窗口大小为10s,窗口推迟关闭时间为3s,现在来了7s、13s数据,窗口会触发计算,水位线为10s,迟到数据5s来了之后会增量进行计算,直到来的数据的事件事件大于等于16的时候才会关窗(这时水位线变为了13)

20f7830482f04334bd846d0adc622d54.png

2.6.3 关窗后的数据使用测输出流接收

00aae5bc6fe14f6ebb8ac0d1e0c450d4.png

乱序迟到数据的总结:

1)watermark中指定 乱序等待的时间

2)如果开窗,可以设置窗口允许迟到

3)关窗后的迟到数据,放入侧输出流

问题:如果watermark等待3s,窗口允许迟到2s,为什么不直接设置watermark等待5s 或者 窗口允许迟到5s呢?

        1. watermark等待时间一般不会设置太高太大 => 会影响计算延迟。窗口关闭触发计算变延后

                如果3s => 窗口第一次触发计算和输出, 13s的数据来 触发计算

                如果5s => 窗口第一次触发计算和输出,15s的数据来 触发计算

        2. 窗口允许迟到 是对 大部分迟到数据的处理,尽量修正结果,让结果准确

                如果只设置允许迟到5s,那么就会导致 频繁重新输出

        =》 1. watermark设置不算特别大的,一般是秒级,在乱序和延迟取舍

                2. 设置一定的窗口允许迟到,只考虑大部分的迟到数据,

                3. 极端小部分迟到很久的数据就不管了,或者放入侧输出流,获取到之后再处理

三、一些常见问题

1. 水位线起什么作用

用来衡量时间时间进度的机制,是不断递增的一个时间戳,表示当前时间点,所有小于该时间戳的事件均到达。

2. 水位线和窗口大小的关系

a:窗口的触发是基于水位线的,当水位线的时间戳大于或等于某个窗口的结束时间,这个窗口就会关闭并触发计算

b:水位线的记录是独立于窗口计算的,它基于事件时间和延迟进行设置。默认是200ms。当解析出事件时间后,会根据当前最大的事件时间 - 延迟时间 - 1ms作为水位线。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值