Flink的窗口,可以理解为一个桶,水龙头下面的水桶的桶,窗口把无限流切割成一个个存储桶,流中数据被分发到对应的桶,再按需对每个桶中收集的数据做计算。
按照驱动类型分
即按照窗口怎么去截取数据来分:
定点发车
,到点窗口就不再收集数据,且触发计算和窗口的销毁关闭人齐发车
按窗口数据分配规则:
滚动窗口:
滑动窗口:
会话窗口:
全局窗口:
调用窗口API前,要确定是否是基于按键分区(Keyed)的数据流KeyedStream来开窗,即调用窗口算子之前,是否有keyBy操作,按键分区的窗口
:
stream.keyBy(...)
.window(...)
对于非按键分区的窗口操作
,原始的DataStream就不会分成多条逻辑流,这时窗口逻辑只能在一个任务(task)上执行,就相当于强行把并行度变成了1
stream.windowAll(...)
对于非按键分区的窗口操作,手动调大窗口算子的并行度也是无效的,windowAll本身就是一个非并行的操作。
对于窗口的操作,分为窗口分配器和窗口函数,前者指明了窗口的类型,是时间窗口、计数窗口、滑动、滚动还是会话窗口。后者定义窗口数据的计算和处理逻辑
stream.keyBy(<key selector>)
.window(<window assigner>)
.aggregate(<window function>)
时间窗口
时间窗口是最常用的窗口类型,又可以细分为滚动、滑动和会话三种:
stream.keyBy(...)
.window(TumblingProcessingTimeWindows.of(Time.seconds(5))) //长度为5秒的滚动窗口
.aggregate(...)
stream.keyBy(...)
//长度为10秒、滑动步长为5秒的滑动窗口
.window(SlidingProcessingTimeWindows.of(Time.seconds(10),Time.seconds(5)))
.aggregate(...)
stream.keyBy(...)
.window(ProcessingTimeSessionWindows.withGap(Time.seconds(10))) //会话的超时时间
.aggregate(...)
看完window方法的传参,窗口分配器由类xxxEventTimeWindows提供:
//滚动
stream.keyBy(...)
.window(TumblingEventTimeWindows.of(Time.seconds(5)))
.aggregate(...)
//滑动
stream.keyBy(...)
.window(SlidingEventTimeWindows.of(Time.seconds(10),Time.seconds(5)))
.aggregate(...)
//会话
stream.keyBy(...)
.window(EventTimeSessionWindows.withGap(Time.seconds(10)))
.aggregate(...)
计数窗口
stream.keyBy(...)
.countWindow(10)
stream.keyBy(...)
.countWindow(10,3) //传入两个参数:size和slide
全局窗口
全局窗口是计数窗口的底层实现,一般在需要自定义窗口时使用。它的定义同样是直接调用.window(),分配器由GlobalWindows类提供。
stream.keyBy(...)
.window(GlobalWindows.create());
使用全局窗口,必须自行定义触发器才能实现窗口计算,否则不起作用。