Bootstrap

Flink窗口及其分类-详细说明

😃😃😃😃😃

更多资源链接,欢迎访问作者gitee仓库:https://gitee.com/fanggaolei/learning-notes-warehouse/tree/master

💎Flink窗口的概念

  Flink 是一种流式计算引擎,主要是来处理无界数据流的,数据源源不断、无穷无尽。想要更加方便高效地处理无界流,一种方式就是将无限数据切割成有限的“数据块”进行处理,这就是所谓的“窗口”(Window)。

image-20221118174543309

  所以在 Flink 中,窗口其实并不是一个“框”,流进来的数据被框住了就只能进这一个窗口。相比之下,我们应该把窗口理解成一个“桶”。在 Flink 中,窗口可以把流切割成有限大小的多个“存储桶”(bucket);每个数据都会分发到对应的桶中,当到达窗口结束时间时,就对每个桶中收集的数据进行计算处理。

image-20221118174647125

⚽窗口的分类

1.按照驱动类型分类

(1)时间窗口(Time Window)

  时间窗口以时间点来定义窗口的开始(start)和结束(end),所以截取出的就是某一时间段的数据。到达结束时间时,窗口不再收集数据,触发计算输出结果,并将窗口关闭销毁。所以可以说基本思路就是“定点发车”

(2)计数窗口(Count Window)

  计数窗口基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口。这相当于座位有限、“人满就发车”,是否发车与时间无关。每个窗口截取数据的个数,就是窗口的大小。

image-20221118175314162

2.按照窗口分配数据的规则分类

(1)滚动窗口(Tumbling Windows)

  滚动窗口有固定的大小,是一种对数据进行“均匀切片”的划分方式。窗口之间没有重叠,也不会有间隔,是“首尾相接”的状态。

image-20221118175539307

(2)滑动窗口(Sliding Windows)

  与滚动窗口类似,滑动窗口的大小也是固定的。区别在于,窗口之间并不是首尾相接的,而是可以“错开”一定的位置。如果看作一个窗口的运动,那么就像是向前小步“滑动”一样。

image-20221118175551399

(3)会话窗口(Session Windows)

  会话窗口顾名思义,是基于“会话”(session)来来对数据进行分组的。这里的会话类似Web 应用中 session 的概念,不过并不表示两端的通讯过程,而是借用会话超时失效的机制来描述窗口。简单来说,就是数据来了之后就开启一个会话窗口,如果接下来还有数据陆续到来,那么就一直保持会话;如果一段时间一直没收到数据,那就认为会话超时失效,窗口自动关闭。

image-20221118175604219

(4)全局窗口(Global Windows)

  还有一类比较通用的窗口,就是“全局窗口”。这种窗口全局有效,==会把相同 key 的所有数据都分配到同一个窗口中;==说直白一点,就跟没分窗口一样。无界流的数据永无止尽,所以这种窗口也没有结束的时候,默认是不会做触发计算的。

image-20221118175650018

🪩窗口 API 概览

1.按键分区(Keyed)和非按键分区(Non-Keyed)

(1)按键分区窗口(Keyed Windows)

  在调用窗口算子之前,是否有 keyBy 操作。

stream.keyBy(...)
 .window(...)

(2)非按键分区(Non-Keyed Windows)

  推荐KeyBy之后再开窗

这时窗口逻辑只能在一个任务(task)上执行,就相当于并行度变成了 1。所以在实际应用中一般不推荐使用这种方式。

stream.windowAll(...)

2.代码中窗口 API 的调用

stream.keyBy(<key selector>)
 	.window(<window assigner>)  //窗口分配器
 	.aggregate(<window function>)  //窗口函数

⚾窗口分配器(Window Assigners)

1.时间窗口

(1)滚动处理时间窗口

   窗口分配器由类 TumblingProcessingTimeWindows 提供,需要调用它的静态方法.of()

stream.keyBy(...)
.window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
.aggregate(...)

   这里.of()方法需要传入一个 Time 类型的参数 size,表示滚动窗口的大小,我们这里创建了一个长度为 5 秒的滚动窗口。

(2)滑动处理时间窗口

  窗口分配器由类 SlidingProcessingTimeWindows 提供,同样需要调用它的静态方法.of()

stream.keyBy(...)
  .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
  .aggregate(...)

   这里.of()方法需要传入两个 Time 类型的参数:size 和 slide,前者表示滑动窗口的大小,后者表示滑动窗口的滑动步长。我们这里创建了一个长度为 10 秒、滑动步长为 5 秒的滑动窗口。

   滑动窗口同样可以追加第三个参数,用于指定窗口起始点的偏移量,用法与滚动窗口完全一致。

(3)处理时间会话窗口

   窗口分配器由类 ProcessingTimeSessionWindows 提供,需要调用它的静态方法.withGap()或者.withDynamicGap()。

stream.keyBy(...)
  .window(ProcessingTimeSessionWindows.withGap(Time.seconds(10)))
  .aggregate(...)

   这里.withGap()方法需要传入一个 Time 类型的参数 size,表示会话的超时时间,也就是最小间隔 session gap。我们这里创建了静态会话超时时间为 10 秒的会话窗口。

(4)滚动事件时间窗口

   窗口分配器由类 TumblingEventTimeWindows 提供,用法与滚动处理事件窗口完全一致。

stream.keyBy(...)
	.window(TumblingEventTimeWindows.of(Time.seconds(5)))
	.aggregate(...)

   这里.of()方法也可以传入第二个参数 offset,用于设置窗口起始点的偏移量。

(5)滑动事件时间窗口

   窗口分配器由类 SlidingEventTimeWindows 提供,用法与滑动处理事件窗口完全一致。

stream.keyBy(...)
	.window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
	.aggregate(...)

(6)事件时间会话窗口

    窗口分配器由类 EventTimeSessionWindows 提供,用法与处理事件会话窗口完全一致

stream.keyBy(...)
	.window(EventTimeSessionWindows.withGap(Time.seconds(10)))
	.aggregate(...)

2.计数窗口

(1)滚动计数窗口

   滚动计数窗口只需要传入一个长整型的参数 size,表示窗口的大小

stream.keyBy(...)
	.countWindow(10)

(2)滑动计数窗口

    与滚动计数窗口类似,不过需要在.countWindow()调用时传入两个参数:size 和 slide,前者表示窗口大小,后者表示滑动步长。

stream.keyBy(...)
	.countWindow(10,3)

   我们定义了一个长度为 10、滑动步长为 3 的滑动计数窗口。每个窗口统计 10 个数据,每隔 3 个数据就统计输出一次结果。

3.全局窗口

   全局窗口是计数窗口的底层实现,一般在需要自定义窗口时使用。它的定义同样是直接调用.window(),分配器由 GlobalWindows 类提供。

stream.keyBy(...)
	.window(GlobalWindows.create());

   需要注意使用全局窗口,必须自行定义触发器才能实现窗口计算,否则起不到任何作用。

;