Flink

tech2022-09-16  89

Window概念

1、一般真实的流都是无界的,怎么样处理无界的数据了?

2、可以把无限的数据流进行切分,从而得到有限的数据集;

3、窗口就是将无限流切割为有限流的一种方式,它会将流数据分发到有限大小的桶(bucket)中进行分析;

window类型

时间窗口(Time Window)

1、滚动时间窗口;

2、滑动时间窗口;

3、会话窗口;

计数窗口(Count Window)

1、滚动时间窗口;

2、滑动时间窗口;

滚动窗口(Tumbling Windows)

1、依据固定的窗口长度对数据进行切分;

2、时间对齐,窗口长度固定,不会有重叠;

滑动窗口(Sliding Window)

1、可以按照固定的长度向后滑动固定的距离;

2、滑动窗口由固定的窗口长度和滑动间隔组成;

3、窗口长度是固定的,可以有重叠(是否重叠和滑动距离有关系);

4、滚动窗口可以看做是滑动窗口的一种特殊情况;

会话窗口(Session Window)

1、指定时间(timeout)没有接收到数据,就会生成新的窗口;

时间语义(TimeStamp) 和水位线(WaterMarker)

时间语义

1、Event Time:事件创建时间;

2、Ingestion Time: 数据进入Flink的时间;

3、Processing Time: 执行操作算子的本地系统时间,与机器相关;

在实际应用中,我们往往更加关心的是Event Time 。

WaterMark(水位线)

什么是WaterMark

1、watermark 是一条特殊的数据记录,用来和window一起解决数据乱序的问题。

2、最新的事件事件 - 固定间隔事件 = watermark时间戳;

3、watermark是单调递增的,如果 (最新的事件事件 - 固定间隔事件)小于之前的事件戳,则watermark不变(watermark不会减少)。

4、如上图 2 、5 这两个watermark 表示,系统认为对应watermark之前的数据都已经到达(其实到底到没到,我们也不知道,我们只是尽最大可能保证数据都已经到了)。

5、只有当 Window 的endTime大于Watermark ,才会触发窗口计算。

WaterMark 的传递

1、上图只选择了一个Task任务进行说明;当前的Task任务有4个输入分区,3个输出分区;

2、Event-time Clock 可以看做是全局的 WaterMark;

3、每个输入分区都有自己的Partition WaterMark, Event-time Clock(时钟)选择了4个分区中最小的WaterMark;之所以选择最小的,就是为了保证每个分区的数据都尽可能的到达。

TimeStamp 和 waterMark的理解和定义

要想说清楚Flink水位线(WaterMark),前提需要弄清楚几个概念。

第一个是时间概念:

在Flink中有三个时间概念,分别是事件时间,采集时间,和系统时间。

事件时间:在客观世界中产生的时间,比如用户点击网页产生了一条时间日志,这个时间就是事件时间。

采集时间:我们用Flink采集日志到达Flink的时间为采集时间。

系统时间:这个时间使我们在写逻辑代码时会调用的时间,比如在程序里面写 System.currentTimeMillis() 命令

当有了时间概念,那我们真正关心的业务时间是哪个呢? 老板不会关心Flink什么时候采集的,更不会关心你什么时候在当前系统调用的时间,所以答案肯定是日志发生的时间,也就是用户什么时候点击的。

那我们怎么通过日志的事件时间对事件进行处理呢?

如下图所示: 当存在网络延时的情况下,本来进入窗口 A 的 2号数据在0-5秒内没有进入窗口A,但是它仍然在采集后出现在A窗口里面,这是为什么?

因为Flink将每条日志的客观产生的时间纪录下来,2号数据就是0-5秒产生的,Flink就会把它放在A窗口。只不过它是在5-10秒的时候被放进去的。那这样的话,我们应该什么时候去关闭窗口呢。

因为有种假设,如果有一个属于这个窗口的数据一年后才过来。那我岂不是要一年才能关窗。所以Flink为了解决这个问题设置了一个过期时间。设置方式如下: 其中10秒为过期时间,element._2为我们从日志中读取中的客观产生的时间戳。

虽然有了过期时间,但是Flink并不会只在过期时间之后闭窗。

实际上,Flink闭窗取决于水位线和过期时间的共同作用,那什么是水位线呢?

水位线指的是Flink内部会在每200ms(默认值,可以设置)生成一个时间戳,它的大小等于当前数据集合里面最大的客观时间减去延时时间。

Flink为什么这么设置呢,我们直接把0-5窗口的数据在延时10秒后关闭不就可以了么。答案是不可以

因为我们这个15秒是系统时间延时的10秒,但是我们要的是真正的客观的时间延时10秒。

这么说可能不太好理解,举个夸张的例子,客观世界中在0-15内(其中5秒的窗口,加上10秒的延时)内产生了十条数据,之后十年就不会再产生数据了,那Flink应不应该关窗?

实际上不应该关窗,因为计算机在不知道下一条日志客观时间的时候,他是不知道此时窗口进行到哪里了。只有在出现客观时间大于十五秒的时候,之前0-5秒的窗口才会关闭。

因此我们为了记录客观时间引入了水位线的概念。用这个数字来记录客观世界的最大时间。

我们只需要比较:水位线是否大于窗口+延时时间,来判断是否该关窗。

当水位线 > 窗口 ------>关窗

当水位线 < 窗口 ------>不关窗

TimeStamp 和 WaterMark 其它设置方式

针对排好序的数据

1、对于排序好的数据,只需要指定时间戳就够了,不需要延迟触发;

自定义

1、Flink 暴露了 TimeStampAssigner 接口,我们可以通过实现这个接口,自定义提取Event Time时间和指定延时时长;如下:

自定义方法需要实现 下面 TimeStampAssigner 两个子类中的任意一个:

最新回复(0)