上篇:初入认识flink窗口运算与时间类型概述
讲解之前,GlobalWindow是干啥用的?其实,它就是一个按照指定的数据条数生成一个Window,与时间无关。话不多说,直接来看看flink窗口那玩意的东西是干啥用的?
主要讲解:
TimeWindow
Non-Keyed和Keyed Windows
一、TimeWindow
1、概述
按照时间生成Window,可以根据窗口实现原理的不同分成三类
1.1、滚动窗口(Tumbling Window)
(1)定义
- 将数据依据固定的窗口⻓度对数据进行切片
(2)特点
- 时间对⻬
- 窗口⻓度固定
- 没有重叠
(3)分配器
- 滚动窗口分配器将每个元素分配到一个指定窗口大小的窗口中,滚动窗口有一个固定的大小,并且不会出现重叠
例如,如果你指定了一个5分钟大小的滚动窗口,窗口的创建
1.2、滑动窗口(Sliding Window)
(1)定义
- 滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口⻓度和滑动间隔组成
(2)特点
- 时间对⻬
- 窗口⻓度固定
- 有重叠
(3)分配器
- 滑动窗口分配器将元素分配到固定⻓度的窗口中,与滚动窗口类似,窗口的大小由窗口大小参数来配置,另一个窗口滑动参数控制滑动窗口开始的频率,因此,滑动窗口如果滑动参数小于窗口大小的话,窗口是可以重叠的,在这种情况下元素会被分配到多个窗口中
1.3、会话窗口(Session Window)
(1)定义
- 由一系列事件组合一个指定时间⻓度的timeout间隙组成,类似于web应用的session,也就是一段时间没有接收到新数据就会生成新的窗口
(2)特点
- 时间无对⻬
(3)分配器
- session窗口分配器通过session活动来对元素进行分组,session窗口跟滚动窗口和滑动窗口相比,不会有重叠和固定的开始时间和结束时间的情况,相反,当它在一个固定的时间周期内不再收到元素,即非活动间隔产生,那个这个窗口就会关闭
- 一个session窗口通过一个session间隔来配置,这个session间隔定义了非活跃周期的⻓度
- 当这个非活跃周期产生,那么当前的session将关闭并且后续的元素将被分配到新的session窗口中去
二、Non-Keyed和Keyed Windows
2.1、Non-Keyed(未分组的Widnows)
2.1.1、概述
(1) 在划分Window之前,首先要确定该DataStream是否调用了key算子将数据按照key进行分组了
(2)如果没有调用keyBy算子,可以调用windowAll方法的返回一个AllWindowedStream,这种window叫做Non-Keyed Windows(未分组的Widnows)
2.1.2、特点
(1)在某一个具体的窗口,所有的数据都会被窗口算子路由到一个subtask中进行运算
(2)如果并行度大于1,下一次生成的window的数据会被路由到其他的subtask中进行运算
2.1.3、方法调用顺序和方法说明
stream.windowAll(…) | 必选方法: 指定相应的窗口分配器 |
[.trigger(…)] | 可选方法: 指定触发器,如果不指定有默认的触发器 |
[.evictor(…)] | 可选方法: 指定剔除器,如果不指定有默认的剔除器 |
[.allowedLateness(…)] | 可选方法: 指定延迟触发时间,如果不指定,默认为0 |
[.sideOutputLateData(…)] | 可选方法: 指定延迟数据的侧流输出的Tag |
.sum/reduce/aggregate/fold/apply() | 必选方法: 指定窗口函数 |
[.getSideOutput(…)] | 可选方法: 指定侧流数据的Tag |
2.1.4、调用的方法
windowAll() | windowAll(): |
trigger() | 指定触发器,如果不指定有默认的触发器 |
allowedLateness() | 指定延迟触发时间,如果不指定,默认为0 |
sideOutputLateData() | 指定延迟数据的侧流输出的tag,用来筛选出打上指定tag的迟到数据 |
sum/reduce/aggregate/fold/apply() | 指定窗口函数,窗口触发时会应该改函数对窗口中的数据进行计算 |
getSideOutput() | 指定侧流数据的tag,筛选出指定tag类型的数据 |
2.2、Keyed Windows(分组的Widnows)
2.2.1、概述
如果事先已经调用了keyBy算子,即对KeyedStream可以调用window方法返回一个WindowedStream,这种window叫做Keyed Windows(分组的Widnows)
2.2.2、特点
(1)窗口中的数据会根据key进行分组,key相同的数据一定会被分到同一个组内,并被路由到同一个subtask中,一个key对应一个组,一个subtask中可以有零到多个组
(2)窗口触发会对每个组进行计算,每个组都会得到一个结果
2.2.3、方法调用顺序和方法说明
stream.keyKey(…) | 先对DataStream调用keyBy得到keyedStream |
.window(…) | 必选方法: 指定相应的窗口分配器 |
[.trigger(…)] | 可选方法: 指定触发器,如果不指定有默认的触发器 |
[.evictor(…)] | 可选方法: 指定剔除器,如果不指定有默认的剔除器 |
[.allowedLateness(…)] | 可选方法: 指定延迟触发时间,如果不指定,默认为0 |
[.sideOutputLateData(…)] | 可选方法: 指定延迟数据的测流输出的Tag |
.sum/reduce/aggregate/fold/apply() | 必选方法: 指定窗口函数 |
[.getSideOutput(…)] | 可选方法: 指定测流数据的Tag |
2.2.4、调用的方法
keyBy() | 按照key进行分组,参数为一或多个分组字段 |
windw() | 划分keyed Windows,参数为指定的Window Assinger |
说明:
- 由于调用windowAll/window算子后会生成会生成WindowedStream/WindowedStream,所以窗口算也是属于Transformation