零基础学Flink:Window & Watermark

2020-07-10 13:18:56 浏览数 (1)

在上一篇文章中,我们学习了flink的时间。 本文我们来一起研究下 window 和 watermark 。

Window

首先,window是无界流数据处理的关键,flink将无界流拆分成无数个window。并对其生命周期进行了定义:

In a nutshell, a window is created as soon as the first element that should belong to this window arrives, and the window is completely removed when the time (event or processing time) passes its end timestamp plus the user-specified allowed lateness (see Allowed Lateness).

一个窗口会在属于其的第一个元素进入的时被创建,当时间(事件时间或处理时间)超过其结束时间加上用户允许的延迟时间后,该窗口被移除。

在flink官方将窗口分为滚动窗口(Tumbling Windows),滑动窗口(Sliding Windows),会话窗口(Session Windows),全局窗口(Global Windows)。全局窗口是一种特殊类型的窗口,不在今天咱们讨论的范围之内。

滚动窗口:滚动窗口分派器(assigner)会将数据元素分派给指定大小的窗口,滚动窗口尺寸固定,相互不会重叠。

滑动窗口:滑动窗口分派器将元素分派给固定长度的窗口。与滚动窗口分派器类似,窗口大小可由参数配置。还有另外一个参数控制滑动窗口的启动频率。因此,如果滑动窗口小于窗口大小,则滑动窗口可以重叠。在这种情况下,元素被分配到多个窗口。如果滑动窗口大于窗口大小,则窗口变成抽样数据。

会话窗口:会话窗口分派器按活动会话对元素进行分组。与滚动窗口和滑动窗口相比,会话窗口不重叠,也没有固定的开始和结束时间。当会话窗口在一段时间内不接收元素时(即,当出现不活动间隙时),它将关闭。

下图,是我认为描述窗口最为清晰的一张了。

这张图,需要从下往上看,最下面定义了原始数据的输入流,即在第一分钟进入2个数据96,第二分钟进入848,以此类推。

倒数第二行,是一个固定时间的滚动窗口,其窗口大小为1分钟。

倒数第三行,是一个滑动窗口,需要数据滑动窗口的窗口尺寸和滑动尺寸。

倒数第四行,是一个固定元素个数的滚动窗口,即每3个元素一滚。

最上面则是一个会话窗口,只要会话有间隙,就会重新构建窗口。

Watermark

通过上面一章的内容,我们可以看出每个窗口都会有开始时间结束时间(一般window的时间窗口为左闭右开的区间范围),在这段时间内,我们是否能拿到所有需要处理的数据,我们就需要watermark来配合了,在之前的文章里,由于理解的原因,我推荐过大家使用翻译水印,但是现在,我觉得还是叫水位线更合适一些。

这里引用一段描述

Watermark是Apache Flink为了处理EventTime 窗口计算提出的一种机制,本质上也是一种时间戳,由Apache Flink Source或者自定义的Watermark生成器按照需求Punctuated或者Periodic两种方式生成的一种系统Event,与普通数据流Event一样流转到对应的下游算子,接收到Watermark Event的算子以此不断调整自己管理的EventTime clock。 Apache Flink 框架保证Watermark单调递增,算子接收到一个Watermark时候,框架知道不会再有任何小于该Watermark的时间戳的数据元素到来了,所以Watermark可以看做是告诉Apache Flink框架数据流已经处理到什么位置(时间维度)的方式。 Watermark的产生和Apache Flink内部处理逻辑如下图所示:

从上文中,我们可以得出两个触发watermark的必要条件

  1. watermark时间 >= 窗口的结束时间
  2. 在窗口的时间范围(左闭右开)内有数据

那么,flink是如何避免数据乱流的呢?我们来看下面一张图

这是一个典型的单通道的场景,首先我们有一个时间事件队列{2,3,1,7,3,5,9,6,12} ,两个wartermark(W4,W9)事件通过时间戳被指派给了窗口(T1-T4)。

数据流入2,3,1进入窗口,7不属于当前事件窗口,所以指派给了新窗口(T4-T8)。

数据继续流入,此时水位线到达W4,触发窗口(T1-T4)计算。

数据继续流入,9被指派给了新窗口(T9-T12)(*笔者注,这个图的事件窗口不对,个人认为是T8-T12

关于多通道的场景,我也推荐云栖的这张图,比官方文档里的要好理解一些,配合上面的案例,相信大家也能读懂。

现在我们已经了解watermark是如何工作的,那么它是如何产生的呢?在flink里主要有两种方式产生watermark,即周期性的(Periodic)和标记性的(Punctuated)

Punctuated:数据流中每一个递增的EventTime都会产生一个Watermark。 在实际的生产中Punctuated方式在TPS很高的场景下会产生大量的Watermark在一定程度上对下游算子造成压力,所以只有在实时性要求非常高的场景才会选择Punctuated的方式进行Watermark的生成。

Periodic:周期性的(一定时间间隔或者达到一定的记录条数)产生一个Watermark。在实际的生产中Periodic的方式必须结合时间和积累条数两个维度继续周期性产生Watermark,否则在极端情况下会有很大的延时。

所以Watermark的生成方式需要根据业务场景的不同进行不同的选择。

好了,关于 window 和 watermark 就暂时说到这了,仅代表个人理解,如有问题,望指正,欢迎转载,著名出处。

后续,会整理一些DEMO与大家分享。

参考资料:

https://yq.aliyun.com/articles/666056

https://ci.apache.org/projects/flink/flink-docs-master/dev/stream/operators/windows.html

https://ci.apache.org/projects/flink/flink-docs-release-1.7/dev/event_timestamps_watermarks.html

https://blog.csdn.net/u4110122855/article/details/81360381

0 人点赞