在批处理中,可以等待一批数据都到齐后统一处理。但Flink是一种流式计算引擎,处理无界数据流,数据源源不断、无穷无尽,想要更加高效地处理无界流,可以将无限数据切割成有限的 数据块 进行处理,即窗口。
窗口的理解
窗口:就是划定的一段时间范围,窗口计算就是对在这范围内的数据进行处理。
正确理解:在Flink中,窗口并不是一个框,而是把流切割成有限大小的多个 存储桶(bucket),每个数据都会分发到对应的桶中,当到达窗口结束时间时,就对每个桶中收集的数据进行计算处理。(类似水桶接水,满了 或 到时间了 换下一个桶,动态创建)。
误解:在Flink中,窗口就是用来处理无界流的核心。把窗口想象成一个固定位置的框,数据源源不断地流过来,到某个时间点窗口该关闭了,就停止收集数据、触发计算并输出结果。但是0-10秒的窗口可以表示为[0,10),左闭右开,乱序+迟到数据,需要延迟2秒,把11秒数据放在[0,10)也不合适,计算错误。
窗口分类
按窗口的驱动类型分:窗口本身是截取有界数据的一种方式,怎样截取数据,即开始和结束数据的截取的标准。
1 时间窗口(Time Window):以时间点来定义窗口的开始和结束,所以截取出的就是某一时间段的数据。到达结束时间时,窗口不再收集数据,触发计算输出结果,并将窗口关闭销毁。定点发车。
2 计数窗口(Count Window):基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口。人齐发车。
按窗口分配数据的规则分:滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)、会话窗口(Session Window)、全局窗口(Global Window)。
滚动窗口
1 滚动窗口有固定的大小,对数据进行 均匀切片。窗口之间没有重叠,也不会有间隔,是 首尾相接 的状态。每个数据都会被分配到一个窗口,且只会属于一个窗口。
只有一个参数:窗口的大小(window size)。
可以基于时间定义,也可以基于数据个数定义;比如可以定义一个长度为1小时的滚动时间窗口,那么每个小时就会进行一次统计;或者定义一个长度为10的滚动计数窗口,就会每10个数进行一次统计。
应用广泛,适合对每个时间段做聚合统计,很多B1分析指标都可以用它来实现。
滑动窗口
2 滑动窗口的大小固定。窗口之间并不是首尾相接的,可以错开一定的位置。
两个参数:窗口大小(window size)、滑动步长(window slide)即窗口计算的频率。窗口在结束时间触发计算输出结果,那么滑动步长就代表了计算频率。
滑动步长<窗口大小时,滑动窗口就会出现重叠,数据可能会被同时分配到多个窗口中。而具体个数由窗口大小和滑动步长的比值(size/slide)来决定。
窗口大小=滑动步长时变为滚动窗口。
适合计算结果更新频率非常高的场景。
会话窗口
3 会话窗口:基于会话(session)来对数据进行分组的。
只能基于时间来定义,窗口大小不固定,开始和结束时间不确定,各个分区之间窗口没有任何关联,会话窗口之间不会重叠,间隔为session gap。
重要参数:会话的超时时间gap,即两个会话窗口之间的最小距离。
如果相邻两个数据到来的时间间隔(Gap)<指定的大小(size),说明还在保持会话,属于同一个窗口;如果gap>size,新来的数据属于新的会话窗口,而前一个窗口就应该关闭了。
适合一些类似保持会话的场景。
全局窗口
4 全局窗口:全局有效,会把相同key的所有数据都分配到同一个窗口中。这种窗口没有结束的时候默认是不会做触发计算的。如果希望它能对数据进行计算处理,还需要自定义 触发器(Trigger)。
没有结束的时间点,一般在希望做更加灵活的窗口处理时自定义使用。Flink中的计数窗口(Count Window),底层就是用全局窗口实现的。