在我们日常使用flink这个框架的过程中,我们会经常使用到窗口,让我们通过下面这篇文章,快速回顾总结一下吧。
Flink的窗口
Flink 是一种流式计算引擎,主要是来处理无界数据流的,数据源源不断、无穷无尽。想要更加方便高效地处理无界流,其中的一种方式是将无限数据切割成有限的“数据块”进行处理,这就是所谓的“窗口”(Window)。
1.1窗口的分类
在 Flink 中,窗口的应用非常灵活,我们可以使用各种不同类型的窗口来实现需求。接下来就从不同的角度,对 Flink 中内置的窗口做一个分类。
1. 按照驱动类型分类
以什么标准来开始和结束数据的截取,我们把它叫作窗口的“驱动类型”。
- 时间窗口
时间窗口以时间点来定义窗口的开始(start)和结束(end),所以截取出的就是某一时间段的数据。到达结束时间时,窗口不再收集数据,触发计算,输出结果,并将窗口关闭销毁。
- 计数窗口
计数窗口基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口。
2. 按照窗口分配数据的规则分类
- 滚动窗口
sensor.window(TumblingProcessingTimeWindows.of(Time.seconds(3)));
//每天翻滚事件的时间窗口偏移-8小时。
sensor.window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(-8))));
滚动窗口有固定的大小,是一种对数据进行“均匀切片”的划分方式。窗口之间没有重叠,也不会有间隔,是“首尾相接”的状态。
- 滑动窗口
sensor.window(SlidingProcessingTimeWindows.of(Time.seconds(5),Time.seconds(2)))
sensor.window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8)))
与滚动窗口类似,滑动窗口的大小也是固定的。区别在于,滑动窗口之间并不是首尾相接的, 而是可以“错开”一定的位置。如果看作一个窗口的运动,那么就像是向前小步“滑动”一样。
- 会话窗口
//静态gap
sensor.window(ProcessingTimeSessionWindows.withGap(Time.minutes(10)))
//动态gap
sensor.window(ProcessingTimeSessionWindows.withDynamicGap((element) -> {
// 确定并返回会话间隙
}))
定义一个时间间隔Gap,如果达到时间间隔,没有新的数据到来,那么之前的数据就会划分为一个窗口。
静态Gap:
时间间隔不变。比如Gap=10,只要10s没有接收到数据,那么就关闭这个窗口,有新的数据来,会再开启一个新的窗口,只要10s内有新的数据来,那么这个10s会被刷新。
动态Gap:
时间间隔动态改变。Gap是一个动态的值,也是说,间隔达到这个动态的值,那么就关闭窗口,有新的数据来,会再开启一个新窗口,只要动态值内有新的数据来,那么这个动态的值就会被刷新。
- 全局窗口
sensor.window(GlobalWindows.create())
这种窗口全局有效,会把相同 key 的所有数据都分配到同一个窗口中;说直白一点,就跟没分窗口一样。无界流的数据永无止尽,所以这种窗口也没有结束的时候,默认是不会触发计算的。如果希望它能对数据进行计算处理, 还需要自定义“触发器”(Trigger)。
1.2窗口的生命周期
1.窗口的创建
窗口的类型和基本信息由窗口分配器(window assigners)指定,但窗口不会预先创建好,而是由数据驱动创建。当第一个应该属于这个窗口的数据元素到达时,就会创建对应的窗口。
2. 窗口计算的触发
除了窗口分配器,每个窗口还会有自己的窗口函数(window functions)和触发器(trigger)。窗口函数可以分为增量聚合函数和全窗口函数,主要定义了窗口中数据计算的逻辑;而触发器则是指定调用窗口函数的条件。
对于不同的窗口类型,触发计算的条件也会不同。例如,一个滚动事件时间窗口,应该在水位线到达窗口结束时间的时候触发计算,属于“定点发车”;而一个计数窗口,会在窗口中元素数量达到定义大小时触发计算,属于“人满就发车”。所以 Flink 预定义的窗口类型都有对应内置的触发器。
当我们设置了允许延迟,那么,如果水位线超过了窗口结束时间、但还没有到达设定的最大延迟时间,这期间内到达的迟到数据也会触发窗口计算。这类似于没有准时赶上班车的人又追上了车,这时车要再次停靠、开门,将新的数据整合统计进来。
3. 窗口的销毁
一般情况下,当时间达到了结束点,就会直接触发计算、输出结果,进而清除状态、销毁窗口。这时窗口的销毁可以认为和触发计算是同一时刻。这里需要注意,Flink 中只对时间窗口(TimeWindow)有销毁机制;由于计数窗口(CountWindow)是基于全局窗口(GlobalWindow)实现的,而全局窗口不会清除状态,所以就不会被销毁。
事件时间语义下,如果设置了允许延迟,那么在水位线到达窗口结束时间时,仍然不会销毁窗口;窗口真正被完全删除的时间点, 是窗口的结束时间加上用户指定的允许延迟时间。
总结
通过上文的阅读,我们可以知道,窗口按照驱动类型分类,分为时间和计数窗口,按照窗口分配数据规则分类,分为滚动、滑动、会话、全局窗口。窗口的创建时间点是第一个属于窗口的元素到达后,不同的窗口有着不同的触发规则,触发器触发以后会进行计算,然后关闭销毁窗口。当然如果设置了允许等待,就不会立刻销毁窗口。