Flink中的窗口类型:
每个窗口只会保存当前的状态,并且在窗口结束后释放掉状态,每来一个窗口都会创建一个新的窗口
时间窗口(窗口时间含左不含右的):
- 滚动窗口
- 滑动窗口
- 会话窗口
计数窗口:
- 滚动计数窗口
- 滑动计数窗口
全局窗口:
- 只有一个并行度,性能较低
滚动窗口:
// 滚动窗口 offset代表偏移量,后续在计算窗口的时间中会用到 TumblingProcessingTimeWindows(long size, long offset) TumblingEventTimeWindows(long size, long offset)
如果您指定大小为 5 分钟的滚动窗口,则将评估当前窗口并每五分钟启动一个新窗口
怎样确定一个滚动窗口的开始时间:
public static long getWindowStartWithOffset(long timestamp, long offset, long windowSize) { return timestamp - (timestamp - offset + windowSize) % windowSize; }
通过源码我们可以看到窗口开始时间的计算方式,offset就是偏移的时间,第一条数据进来后,其实所有的窗口就已经确定好了
在没有偏移量的情况下,每小时翻滚窗口与纪元对齐,即您将获得诸如1:00:00.000 - 1:59:59.999,2:00:00.000 - 2:59:59.999等等的窗口 。
如果你想改变它,你可以给出一个偏移量。随着15分钟的偏移量,你会拿到例如 1:15:00.000 - 2:14:59.999,2:15:00.000 - 3:14:59.999等等的窗口。
offset会在窗口时间内往后推
offset几个注意点:
窗口长度为一天的时候,需要将偏移量设置为 Time.hours(-8)
测试代码如下:
public class OffsetTest { public static void main(String[] args) { // 测试偏移量 long timestamp = System.currentTimeMillis(); long offset = 0 ; long windowSize = 24 * 60 * 60 * 1000 ; long windowStartWithOffset = getWindowStartWithOffset(timestamp, offset, windowSize); DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(windowStartWithOffset/1000, 0, ZoneOffset.ofHours(8)); System.out.println(localDateTime.format(formatter1)); } public static long getWindowStartWithOffset(long timestamp, long offset, long windowSize) { return timestamp - (timestamp - offset + windowSize) % windowSize; } }
打印的结果为 2021-08-27 08:00:00
所以我们要将偏移量前移8小时。
对于其它时长是否需要指定偏移量,可以根据代码自己调试。
滑动窗口:
// 滑动窗口 SlidingProcessingTimeWindows(long size, long slide, long offset) SlidingEventTimeWindows(long size, long slide, long offset)
怎样确定一个滑动窗口:
public static long getWindowStartWithOffset(long timestamp, long offset, long windowSize) { return timestamp - (timestamp - offset + windowSize) % windowSize; } long lastStart = TimeWindow.getWindowStartWithOffset(timestamp, offset, slide); for (long start = lastStart; start > timestamp - size; start -= slide) { windows.add(new TimeWindow(start, start + size)); }
滑动窗口的输出频率是按照滑动步长来进行输出的
如果没有偏移,每小时窗口半小时滑动,那么你会得到 1:00:00.000 - 1:59:59.999,1:30:00.000 - 2:29:59.999等等的窗口。
如果你想改变它,你可以给出一个偏移量。随着15分钟的偏移量,你会拿到例如 1:15:00.000 - 2:14:59.999,1:45:00.000 - 2:44:59.999等等的窗口。
对于滑动窗口的offset,由于计算方式和滚动窗口是一样的,所以窗口长度为一天的时候,也需要将偏移量设置为 Time.hours(-8) 。
会话窗口:
// 会话窗口 ProcessingTimeSessionWindows(long sessionTimeout) EventTimeSessionWindows(long sessionTimeout)
在会话窗口出让方按活动的会话组中的元素。与滚动窗口和滑动窗口相比,会话窗口不重叠,也没有固定的开始和结束时间。
相反,当会话窗口在特定时间段内没有接收到元素时,即,当发生不活动间隙时,会话窗口将关闭。
会话窗口分配器可以配置为静态会话间隙或 会话间隙提取器功能,该功能定义了不活动时间的长度。当此时间段到期时,当前会话将关闭,后续元素将分配给新的会话窗口。
计数窗口:
countWindow(long size) countWindow(long size, long slide)
当窗口元素个数达到n个时候触发窗口的计算
全局窗口:
.window(GlobalWindows.create())