Flink中的窗口类型:

每个窗口只会保存当前的状态,并且在窗口结束后释放掉状态,每来一个窗口都会创建一个新的窗口

时间窗口(窗口时间含左不含右的):

  • 滚动窗口
  • 滑动窗口
  • 会话窗口

计数窗口:

  • 滚动计数窗口
  • 滑动计数窗口

全局窗口:

  • 只有一个并行度,性能较低

滚动窗口:

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小时。

对于其它时长是否需要指定偏移量,可以根据代码自己调试。

滑动窗口:

flink窗口简介_滑动窗口_02

// 滑动窗口
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) 。

会话窗口:

flink窗口简介_并行度_03

// 会话窗口
ProcessingTimeSessionWindows(long sessionTimeout)
EventTimeSessionWindows(long sessionTimeout)

在会话窗口出让方按活动的会话组中的元素。与滚动窗口和滑动窗口相比,会话窗口不重叠,也没有固定的开始和结束时间。

相反,当会话窗口在特定时间段内没有接收到元素时,即,当发生不活动间隙时,会话窗口将关闭。

会话窗口分配器可以配置为静态会话间隙或 会话间隙提取器功能,该功能定义了不活动时间的长度。当此时间段到期时,当前会话将关闭,后续元素将分配给新的会话窗口。

计数窗口:

countWindow(long size)
countWindow(long size, long slide)

当窗口元素个数达到n个时候触发窗口的计算

全局窗口:

.window(GlobalWindows.create())