window
- 一般真实的流都是无界的,怎么处理无界的数据?
- 可以把无限的数据流进行切分,得到有限的数据集进行处理 --也就是得到有界流
- 窗口就是将无限流切割为有限流的一种方式,它会将流数据分发到有限大小的桶中进行分析
窗口类型
时间窗口(time window)
滚动时间窗口(Tumbling Window)
- 将数据依据固定的窗口长度对数据进行切分
- 时间对齐,窗口长度固定,没有重叠,每条数据只能划分到确定的一个窗口里面
- 适用场景:适合做BI统计等(做每个时间段的聚合计算)。
滑动时间窗口(Sliding Window)(实际应用最多)
- 滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成
- 窗口长度固定,可以有重叠。
- 适用场景:对最近一个时间段内的统计(求某接口最近5min的失败率来决定是否要报警)。
会话时间窗口(Session Window)
- 由一系列事件组合一个指定时间长度的timeout间隙组成,有就是有一段时间没有接收到数据就会生成一个新的窗口
- 窗口长度不固定,没有重叠,每条数据只能划分到确定的一个窗口里面
计数窗口(count window)
滚动计数窗口
- 窗口消息条数固定,没有重叠,每条数据只能划分到确定的一个窗口里面
滑动计数窗口
- 窗口消息条数固定,可以有重叠,每条数据可能划分到多个窗口里面
windiw API
* Keyed Windows
<可以理解为按照原始数据流中的某个key进行分类,拥有同一个key值的数据流将为进入同一个window,多个窗口并行的逻辑流>
stream
.keyBy(...) <- keyed versus non-keyed windows
.window(...) <- required: "assigner"
[.trigger(...)] <- optional: "trigger" (else default trigger)
[.evictor(...)] <- optional: "evictor" (else no evictor)
[.allowedLateness(...)] <- optional: "lateness" (else zero)
[.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
.reduce/aggregate/fold/apply() <- required: "function"
[.getSideOutput(...)] <- optional: "output tag"
* Non-Keyed Windows
<不做分类,每进入一条数据即增加一个窗口,多个窗口并行,每个窗口处理1条数据>
stream
.windowAll(...) <- required: "assigner"
[.trigger(...)] <- optional: "trigger" (else default trigger)
[.evictor(...)] <- optional: "evictor" (else no evictor)
[.allowedLateness(...)] <- optional: "lateness" (else zero)
[.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
.reduce/aggregate/fold/apply() <- required: "function"
[.getSideOutput(...)] <- optional: "output tag"
用`[ ]`包含的内容,其中的方法均为可选函数,如需了解可以查阅一下官方文档。
- 每个window必备的是触发器Trigger和一个附加在window上的函数
窗口分配器–WindAssinger
我们可以用.window()来定义一个窗口,然后基于这个window去做一些聚合或者其他的操作。
注意 window必须在KeyBy之后才能使用。
dataStream的开窗方法是.WindiwAll()
Flink提供了更简单的.timeWindow和.countWindow方法,用于定义时间窗口和计数窗口
window方法接收的输入参数是一个WindowAssigner
WindowAssigner负责将每条数据分发到正确的window中
flink提供了通用的WindowAssigner
- 滚动窗口(Tumbling Window)
.timeWindow(Time.seconds(15))
- 滑动窗口(Sliding Window)
.timeWindow(Time.seconds(15),Time.seconds(5))
- 会话窗口(Session Window)
.window(EventTimeSessionWindows.withGap(Time.minutes(10)))
- 全局窗口(global window不会结束的窗口) 用于自定义窗口结束
.window(GlobalWindows.create())
- 滚动计数窗口
.countWindow(5)
- 滑动计数窗口
.countWindow(10,2)
窗口函数 (window function)
窗口函数是触发器在确认窗口数据到达完毕后,执行的函数。
flink提供了两类窗口函数,
- AggerateFunction/ReduceFunction/FoldFunction/… 聚合函数
此类为数据计算函数,适用于仅计算,无需做时间窗口的情况。
AggerateFunction为用户自定义函数,可以按照个人需求做各类统计。
- WindowFunction/ProcessWindowFunction/… 全窗口函数
此类为做窗口函数,适用于无需计算只做时间窗口统计的情况。(ps.貌似很少有这样的情况)
聚合函数+全窗口函数
两种方式的结合适用于需要进行计算后再做滑动窗口统计结果的情况。
(直接对全部SourceData数据做WindowFunction消耗会较大,所以先做计算,提取出需要的特征、结果后,减轻窗口函数的压力。)
增量聚合函数 incremental aggregation functions
- 每条数据进来都进行计算,保持一个简单的状态
- ReduceFunction、AggragationFunction
适合聚合
窗口的输出要在窗口关闭之后,全窗口会存下所有数据最后再进行计算,
相对于增量聚合函数更占空间而且可以提前计算,缺点是增量聚合函数比较简单。
全窗口函数 full window function
- 先把所有窗口的数据收集起来,等到计算的时候会遍历所有的数据
- ProcessWindowFunction 也是8中ProcessFunction之一
适合排序
不过ProcessWindowFunction可以跟其他的窗口函数(ReduceFunction, AggregateFunction, or FoldFunction)结合使用,其他函数接受增量信息,ProcessWindowFunction接受窗口的元数据。
windowFunction
dataStream -> KeyBy -> KeyedStream->window -> windowStream -> 增量聚合/全窗口函数 ->dataStream
dataStream ->WindowAll -> allwindowedStream -> 增量聚合/全窗口函数 ->dataStream