Flink 窗口
在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。虽然Flink可以做到每来一个消息就处理一次,但是更多时候我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户访问了我们的网页,所以Flink引入了窗口(Window)概念。
窗口将一个无限数据流拆分成有限的数据集合(在Flink中简称为“桶”),并使得我们很方便地在上面做一些操作。窗口就是从 Streaming 到 Batch 的一个桥梁。
在 Flink 的实现中,会有具体的策略决定何时创建一个桶,数据该分配到哪个桶,而后续的操作是基于条件触发的,当然这个条件是可以自定义的,Flink 内部也有默认的实现,一旦条件达到,后续的操作就会发生,将桶内的数据发送给操作函数。这便是窗口在整个过程中起到的作用。
Flink 会有具体的策略决定何时创建桶以及数据该分配到哪个桶,那么有哪些策略呢?这些策略在 Flink 中的区分就是窗口的类型:
- 滚动窗口(Tumbling Window, 无重叠)
- 滑动窗口 (Sliding Window, 有重叠)
- 会话窗口(Session Window, 活动间隙)
这些窗口具体什么时候会用到呢?比如我们要计算每隔5分钟的车流量,那就需要滚动窗口,每5分钟累计一次。但是如果希望每分钟计算一下最近5分钟的车流量呢,那就需要滑动窗口,滑动的大小为1分钟。而如果要统计用户在一次网页交互的会话内点击页面的次数,那么这个时候就需要用会话窗口了。当然了,如果这几个内置的窗口不够用的话,还可以自定义。
桶已经创建好了,数据也已经分配到具体的桶了,那么何时触发后续的操作函数呢?这个在 Flink 由触发器来规定。触发器会决定一个窗口何时被计算或清除(即清除窗口中的元素)。因而每个窗口都会有一个触发器。再接着举上面的例子说吧,如果要5分钟统计一次的话,那么显然需要计时,每隔5分钟就触发一次。Flink 内部已经对常用的窗口实现了默认的触发器,如果不满足的话也可以使用相应的 API 来自定义。
在实际的数据产生到处理的过程中,出现数据的延迟再正常不过了,那么我们怎么让迟到的数据加入到窗口中呢?在 Flink 中提供了允许延迟的 API,只要数据还没有到窗口的最后时间加上延迟时间,那么依然会被加入到窗口中,而且有可能再次触发后续的操作函数,这取决于具体的触发器的实现。