Flink Window 窗口机制
一、总览
-
Window 是flink处理无限流的核心,Windows将流拆分为有限大小的“桶”,我们可以在其上应用计算。
-
Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层引擎是一个流式引擎,在上面实现了流处理和批处理。
-
而窗口(window)就是从 Streaming 到 Batch 的一个桥梁。
-
Flink 提供了非常完善的窗口机制。
-
在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。
-
当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户点击了我们的网页。
-
在这种情况下,我们必须定义一个窗口,用来收集最近一分钟内的数据,并对这个窗口内的数据进行计算。
-
窗口可以是基于时间驱动的(Time Window,例如:每30秒钟)
-
也可以是基于数据驱动的(Count Window,例如:每一百个元素)
-
同时基于不同事件驱动的窗口又可以分成以下几类:
- 翻滚窗口 (Tumbling Window, 无重叠):一条记录只属于一个窗口
- 滑动窗口 (Sliding Window, 有重叠):一条记录属于多个窗口
- 会话窗口 (Session Window, 活动间隙):一条记录一个窗口
- 全局窗口 (略)
-
Flink要操作窗口,先得将StreamSource 转成WindowedStream

二、Tumbling Window(翻滚窗口)
-
翻滚窗口能将数据流切分成不重叠的窗口,每一个事件只能属于一个窗口
-
翻滚窗具有固定的尺寸,不重叠。
-
例图:

-
基于时间驱动 timeWindow(Time.seconds(n))
-
基于事件驱动 countWindow(n)
案例:
package cn.kgc.kb09.Window
import cn.kgc.kb09.Tramsfrom.WaterSensor
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
/**
* Flink 窗口函数
* Tumbling Window (滚动窗口) 窗口周期 10秒
* 找出最小空高
*
* 从socket端口接收字符串格式为"sensor_1,1549044122,10"数据
* 接收到字符串后将字符串流转换成WaterSensor流 DataStream[WaterSensor]
*/
// 定义样例类
case class WaterSensor(id:String,ts:Long,vc:Double)
object WindowDemo {
def main(args: Array[String]): Unit = {
// 创建执行的环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1) // 设置并行度
// 从socket端口接收数据
val stream = env.socketTextStream("192.168.247.201",7777)
// 转换成样例类
val dataStream = stream.map(x => {
// 根据逗号切割 获取每个元素
val strings = x.split(",")
WaterSensor(strings(0).trim, strings(1).trim.toLong, strings(2).trim.toDouble)
})
val dataStream2: DataStream[(String, Double)] = dataStream.map(data => (data.id, data.vc))
val dataStream3: KeyedStream[(String, Double), String] = dataStream2.keyBy(_._1)
// Tumbling Window 滚动窗口
val dataStream4: WindowedStream[(String, Double), String, TimeWindow] = dataStream3.timeWindow(Time.seconds(10))
val minDataStream: DataStream[(String, Double)] = dataStream4.reduce((x, y) => (x._1,x._2.min(y._2)))
// 打印
dataStream.print("orig")
minDataStream.print("min")
// 执行
env.execute("windowDemo")
}
}
运行代码,在Linux上执行nc -lk 7777命令


三、Sliding Window(滑动窗口)
-
滑动窗口和翻滚窗口类似,区别在于:滑动窗口可以有重叠的部分。
-
在滑窗中,一个元素可以对应多个窗口。
-
例图:

-
基于时间驱动 timeWindow(Time.seconds(n), Time.seconds(m))
-
基于事件驱动 countWindow(n, m)
案例:
package cn.kgc.kb09.Window
import cn.kgc.kb09.Tramsfrom.WaterSensor
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
/**
* Flink 窗口函数
* Sliding Window (滑动窗口) 窗口周期 10秒 滑动周期 5秒
* 找出最小空高
*
* 从socket端口接收字符串格式为"sensor_1,1549044122,10"数据
* 接收到字符串后将字符串流转换成WaterSensor流 DataStream[WaterSensor]
*/
// 定义样例类
case class WaterSensor(id:String,ts:Long,vc:Double)
object WindowDemo {
def main(args: Array[String]): Unit = {
// 创建执行的环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1) // 设置并行度
// 从socket端口接收数据
val stream = env.socketTextStream("192.168.247.201",7777)
// 转换成样例类
val dataStream = stream.map(x => {
// 根据逗号切割 获取每个元素
val strings = x.split(",")
WaterSensor(strings(0).trim, strings(1).trim.toLong, strings(2).trim.toDouble)
})
val dataStream2: DataStream[(String, Double)] = dataStream.map(data => (data.id, data.vc))
val dataStream3: KeyedStream[(String, Double), String] = dataStream2.keyBy(_._1)
// Sliding Window 滑动窗口
val dataStream4: WindowedStream[(String, Double), String, TimeWindow] = dataStream3.timeWindow(Time.seconds(10),Time.seconds(5))
val minDataStream: DataStream[(String, Double)] = dataStream4.reduce((x, y) => (x._1,x._2.min(y._2)))
// 打印
dataStream.print("orig")
minDataStream.print("min")
// 执行
env.execute("windowDemo")
}
}
运行代码,在Linux上执行nc -lk 7777命令


四、Session Window(会话窗口)
-
会话窗口不重叠,没有固定的开始和结束时间
-
与翻滚窗口和滑动窗口相反, 当会话窗口在一段时间内没有接收到元素时会关闭会话窗口。
-
后续的元素将会被分配给新的会话窗口
-
例图:

1759

被折叠的 条评论
为什么被折叠?



