Windows 计算是流式计算中非常常用的数据计算方式之一, 通过按照固定时间或长度将数据流切分成不同的窗口, 然后对数据进行相应的聚合运算, 从而得到一定时间范围内的统计结果。
一. Window分类
1. Global Window 和 Keyed Window
在运用窗口计算时,Flink根据上游数据集是否为KeyedStream类型,对应的Windows 也 会有所不同。
- Keyed Window: 上游数据集如果是KeyedStream类型, 则调用 DataStream API的 window() 方法, 数据会根据 Key在不同的Task实例中并行分别计算, 最后得出针对每个Key统计的结果。
- Global Window: 如果是Non-Keyed类型, 则调用WindowsAll()方法, 所有的数据都会在窗口算子中由到一个Task中计算, 并得到全局统计结果。
2. Time Window(时间窗口)
根据不同的业务场景, Time Window也可以分为三种类型, 分别是滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)和会话窗口(Session Window)
1. 滚动窗口(Tumbling Window)
-
滚动窗口是根据固定时间进行切分,且窗口和窗口之间的元素互不重叠。这种类型的窗 口的最大特点是比较简单。只需要指定一个窗口长度(window size).
-
问题: 每隔10s统计每个基站的日志数量
package com.hjf.window import com.hjf.dataSource.{ CustomerSource, StationLog} import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows import org.apache.flink.streaming.api.windowing.time.Time object TestTumblingWindow { def main(args: Array[String]): Unit = { val streamEnv: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment streamEnv.setParallelism(1) import org.apache.flink.streaming.api.scala._ val stream: DataStream[StationLog] = streamEnv.addSource(new CustomerSource) stream.map(log => (log.sid, 1)).keyBy(_._1) // 指定时间窗口的大小 // .timeWindow(Time.seconds(10)) .window(TumblingEventTimeWindows.of(Time.seconds(10))) .sum(1).print() streamEnv.execute() } }
2. 滑动窗口(Sliding Window)
-
滑动窗口也是一种比较常见的窗口类型, 其特点是在滚动窗口基础之上增加了窗口滑动时间(Slide Time), 且允许窗口数据发生重叠。当Windows size固定之后, 窗口并不像滚动窗口按照Windows Size向前移动, 而是根据设定的 Slide Time向前滑动. 窗口之间的 数据重叠大小根据Windows size和Slide time决定, 当Slide time小于Windows size便会发生窗口重叠, Slide size大于 Windows size就会出现窗口不连续, 数据可能不能在 任何一个窗口内计算, Slide size和Windows size相等时, Sliding Windows其实就是Tumbling Windows。
-
问题: 每隔5秒计算最近10秒内,每个基站的日志数量
package com.hjf.window import com.hjf.dataSource.{ CustomerSource, StationLog} import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment import org.apache.flink.streaming.api.windowing.time.Time object TestSlidingWindow { def main(args: Array[String]): Unit = { val streamEnv: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment streamEnv.setParallelism(1) import org.apache.flink.streaming.api.scala._ val stream: DataStream[StationLog] = streamEnv.addSource(new CustomerSource) stream.map(log => (log.sid, 1)).keyBy