目录
窗口
Flink “存储桶”
窗口分类
按照驱动类型分类
按照窗口分配数据的规则分类
滚动窗口
滑动窗口
会话窗口
全局窗口
窗口的生命周期
窗口
窗口:将无限数据切割成有限的“数据块”进行处理,以便更高效地处理无界流
在处理无界数据流时,把无界流进行切分,每一段数据分别进行聚合,结果只输出一次。这就相当于将无界流的聚合转化为了有界数据集的聚合
Flink “存储桶”
在 Flink 中,窗口可以把流切割成有限大小的多个“存储桶”(bucket);每个数据都会分发到对应的桶中,当到达窗口结束时间时,就对每个桶中收集的数据进行计算处理
窗口处理过程:
窗口创建:
Flink 中窗口并不是静态准备好的,而是动态创建——当有落在这个窗口区间范围的数据达到时,才创建对应的窗口
窗口分类
按照驱动类型分类
驱动类型,即窗口以什么标准来开始和结束数据的截取
按照时间段截取:时间窗口
窗口大小:用结束时间减去开始时间,得到这段时间的长度,就是窗口的大小
flink中用
TimeWindow
类来表示时间窗口:可以看到,窗口的时间范围是左闭右开的区间
按照固定的个数截取:计数窗口
计数窗口基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口
按照窗口分配数据的规则分类
滚动窗口
滚动窗口有固定的大小,是一种对数据进行“均匀切片”的划分方式;
窗口之间没有重叠,也不会有间隔,是“首尾相接”的状态,所以每个数据都会被分配到一个窗口,而且只会属于一个窗口
滚动窗口可以基于时间定义,也可以基于数据个数定义;需要的参数只有一个,就是窗口的大小(window size)。比如我们可以定义一个长度为 1 小时的滚动时间窗口,那么每个小时就会进行一次统计;或者定义一个长度为 10 的滚动计数窗口,就会每 10 个数进行一次统计
滑动窗口
滑动窗口的大小也是固定的,但窗口之间并不是首尾相接的,而是可以“错开”一定的位置
参数:窗口大小和滑动步长
窗口大小是固定的,代表了两个窗口结束时间的间隔
滑动步长代表了窗口计算的频率。滑动的距离代表了下个窗口开始的时间间隔
当滑动步长小于窗口大小时,滑动窗口就会出现重叠,这时数据也可能会被同时分配到多个窗口中;具体的个数,就由窗口大小和滑动步长的比值来决定;
比如我们定义的窗口长度为 1 小时、滑动步长为 30 分钟,那么对于 8 点 55 分的数据,应该同时属于[8 点, 9 点)和[8 点半, 9 点半)两个窗口;而对于 8 点 10 分的数据,则同时属于[8点, 9 点)和[7 点半, 8 点半)两个窗口
会话窗口
- 数据来了之后就开启一个会话窗口,如果接下来还有数据陆续到来,那么就一直保持会话;如果一段时间一直没收到数据,那就认为会话超时失效,窗口自动关闭
- 会话窗口只能基于时间来定义;因为“会话”终止的标志就是“隔一段时间没有数据来”
- 参数:会话的超时时间
- 会出现的问题:相邻两个数据的时间间隔 gap大于指定的 size,我们认为它们属于两个会话窗口,前一个窗口就关闭;可在数据乱序的情况下,可能会有迟到数据,它的时间戳刚好是在之前的两个数据之间的。这样一来,之前我们判断的间隔中就不是“一直没有数据”,而缩小后的间隔有可能会比 size 还要小——这代表三个数据本来应该属于同一个会话窗口
- 解决方法:每来一个新的数据,都会创建一个新的会话窗口;然后判断已有窗口之间的距离,如果小于给定的 size,就对它们进行合并(merge)操作
全局窗口
- 全局有效,会把相同 key 的所有数据都分配到同一个窗口中(就相当于没有分窗口)
- 默认是不会做触发计算的。如果希望它能对数据进行计算处理,还需要自定义“触发器”(Trigger)
Flink 中的计数窗口(Count Window),底层就是用全局窗口实现的
窗口的生命周期
①窗口的创建:窗口的类型和基本信息由窗口分配器指定,但是窗口的创建是由数据驱动创建的,当第一个应该属于这个窗口的数据元素到达时,就会创建对应的窗口
②窗口计算的触发:触发器触发窗口函数的执行,进行数据计算
③窗口的销毁:一般情况下,当时间达到了结束点,就会直接触发计算输出结果、进而清除状态销毁窗口;在特殊的场景下,窗口的销毁和触发计算会有所不同
事件时间语义下,如果设置了允许延迟,那么在水位线到达窗口结束时间时,仍然不会销毁窗口;窗口真正被完全删除的时间点,是窗口的结束时间加上用户指定的允许延迟时间
④窗口API: