Flink:时间与窗口
来源:https://blog.csdn.net/k_wzzc/article/details/90582507
Flink学习笔记:时间与窗口
1. 时间
在flink中定义了三类时间:
事件时间(Event Time):即事件实际发生的时间。
处理时间(Processing Time):事件被处理的时间。
进入时间(Ingestion Time):事件进入流处理框架的时间
下图很好的说明了三种时间的区别与联系
其中时间时间和处理时间是比较常用,根据应用程序的不同以及结果准确性要求可以定义不同的时间,在flink中应用程序中应当显示的定义时间特征
// 显示设置flink 时间特征:IngestionTime 、EventTime、ProcessingTime
// 如果不设置 默认为 ProcessingTime
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
当采用事件时间定义窗口时,可以利用flink的WaterMark机制处理乱序时间流。
2. 窗口
窗口时flink中的一类算子,是DataStream的逻辑边界,用于将许多事件按照时间或者其他特征分组,从而将每一组作为整体进行分析。在开发中最常用的是时间窗口和计数窗口。
2.1 时间窗口
2.1.1 滚动窗口
滚动窗口设置
val dataSource: DataStream[(Int, Int )] = env.addSource(kafkaConsumer)
.map(...)
// 设置处理时间长度为30s的滚动窗口,也可以定义为事件时间的窗口 TumblingEventTimeWindows
dataSource.keyBy(0)
.window( TumblingProcessingTimeWindows.of( Time.seconds(30)) )
// 也可以这样写
dataSource.keyBy(0)
.timeWindow(Time.seconds(30))
2.1.2滑动窗口
滑动窗口设置
// 设置处理时间滑动窗口:窗口长度为30s,步长5s
dataSource.keyBy(0)
.window(TumblingProcessingTimeWindows.of(Time.seconds(30),Time.seconds(5)))
.sum(1)
dataSource.keyBy(0)
.timeWindow(Time.seconds(30),Time.seconds(5))
.sum(1)
滚动窗口和滑动窗口的区别在于滑动窗口的窗口在不同时间区间之间有重叠。
2.2 计数窗口
计数窗口与时间窗口相似,只不过分组依据不在是时间而是元素的数量,计数窗口也分为滚动计数窗口与滑动计数窗口,但是在使用计数窗口时需要注意的是,只有当元素的个数满足设定的窗口长度时才会触发该窗口的计算,如果不满足元素个数,则该窗口就不会触发计算,窗口长时间占用资源会就会造成资源浪费。一种解决办法是用时间窗口来触发超时。
// 设置窗口长度为10滚动计数窗口
dataSource.keyBy(0).countWindow(10).sum(1)
// 设置窗口长度为10,步长为2的滑动计数窗口
dataSource.keyBy(0).countWindow(10,2).sum(1)
会话窗口
会话窗口在一些常见的真实场景中非常有用,这些场景既不适合用滚动窗口,也不适用滑动窗口。
会话窗口(Session Windows)主要是将某段时间内活跃度较高的数据聚合成一个窗口进行计算,窗口的触发的条件是 Session Gap,是指在规定的时间内如果没有数据活跃接入,则认为窗口结束,然后触发窗口计算结果。
需要注意的是如果数据一直不间断地进入窗口,也会导致窗口始终不触发的情况。与滑动窗口、滚动窗口不同的是,Session Windows 不需要有固定 windows size 和 slide time,只需要定义 session gap,来规定不活跃数据的时间上限即可。
3 其他窗口
flink除了提供时间窗口和计数窗口,还提供了会话窗口,会话(session)是指一段持续活跃的期间,由活跃间隙分隔开,一个session没有固定的时长和步长,需要自己定义处理机制。例如同样是在网站购买商品,有的人经过 搜索 -> 点击 -> 购买 这三个步骤完成一次订单交易,耗时可能很长,也可能很短;有的人则是经过 搜索 -> 点击 -> 查看 ->客服沟通…购买 一系列的操作之后才完成的一次订单交易。更详细的讲解介绍可以参考以下两篇文章:Flink 原理与实现:Session Window、Flink流计算编程–看看别人怎么用Session Window。与此同时,为了满足某些特殊的需求,Flink还可以通过自定义window来实现。