大数据开发-Flink-窗口全解析
Flink窗口背景
Flink认为Batch是Streaming的一个特例,因此Flink底层引擎是一个流式引擎,在上面实现了流处理和批处理。而Window就是从Streaming到Batch的桥梁。通俗讲,Window是用来对一个无限的流设置一个有限的集合,从而在有界的数据集上进行操作的一种机制。流上的集合由Window来划定范围,比如“计算过去10分钟”或者“最后50个元素的和”。Window可以由时间(Time Window)(比如每30s)或者数据(Count Window)(如每100个元素)驱动。DataStream API提供了Time和Count的Window。
一个Flink窗口应用的大致骨架结构如下所示:
// Keyed Window
stream
.keyBy(...) <- 按照一个Key进行分组
.window(...) <- 将数据流中的元素分配到相应的窗口中
[.trigger(...)] <- 指定触发器Trigger(可选)
[.evictor(...)] <- 指定清除器Evictor(可选)
.reduce/aggregate/process() <- 窗口处理函数Window Function
// Non-Keyed Window
stream
.windowAll(...) <- 不分组,将数据流中的所有元素分配到相应的窗口中
[.trigger(...)] <- 指定触发器Trigger(可选)
[.evictor(...)] <- 指定清除器Evictor(可选)
.reduce/aggregate/process() <- 窗口处理函数Window Function
Flink窗口的骨架结构中有两个必须的两个操作:
- 使用窗口分配器(WindowAssigner)将数据流中的元素分配到对应的窗口。
- 当满足窗口触发条件后,对窗口内的数据使用窗口处理函数(Window Function)进行处理,常用的Window Function有
reduce、aggregate、process
滚动窗口
基于时间驱动
将数据依据固定的窗口长度对数据进行切分,滚动窗口下窗口之间之间不重叠,且窗口长度是固定的。我们可以用TumblingEventTimeWindows和TumblingProcessingTimeWindows创建一个基于Event Time或Processing Time的滚动时间窗口。窗口的长度可以用org.apache.flink.streaming.api.windowing.time.Time中的seconds、minutes、hours和days来设置。

//关键处理案例
KeyedStream<Tuple2<String, Integer>, Tuple> keyedStream = mapStream.keyBy(0);
// 基于时间驱动,每隔10s划分一个窗口
WindowedStream<Tuple2<String, Integer>, Tuple, TimeWindow> timeWindow =
keyedStream.timeWindow(Time.seconds(10));
// 基于事件驱动, 每相隔3个事件(即三个相同key的数据), 划分一个窗口进行计算
// WindowedStream<Tuple2<String, Integer>, Tuple, GlobalWindow> countWindow =
keyedStream.countWindow(3);
// apply是窗口的应用函数,即apply里的函数将应用在此窗口的数据上。
timeWindow.apply(new MyTimeWindowFunction()).print();
// countWindow.apply(new MyCountWindowFunction()).print();
基于事件驱动
当我们想要每100个用户的购买行为作为驱动,那么每当窗口中填满100个”相同”元素了,就会对窗口进行计算,很好理解,下面是一个实现案例
public class MyCountWindowFunction implements WindowFunction<Tuple2<String, Integer>,
String, Tuple, GlobalWindow> {
@Override
public void apply(Tuple tuple, GlobalWindow window, Iterable<Tuple2<String, Integer>>
input, Collector<String> out) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
int sum = 0;
for (Tuple2<String, Integer> tuple2 : input){
sum += tuple2.f1;
}
//无用的时间戳,默认值为: Long.MAX_VALUE,因为基于事件计数的情况下,不关心时间。
long maxTimestamp = window.maxTimestamp();
out.collect("key:" + tuple.getField(0) + " value: " + sum + "| maxTimeStamp :"+ maxTimestamp + "," + format.format(maxTimestamp)
);
}
}
滑动时间窗口
动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成,特点:窗口长度固定,可以有重叠,滑动窗口以一个步长(Slide)不断向前滑动,窗口的长度固定。使用时,我们要设置Slide和Size。Slide的大小决定了Flink以多大的频率来创建新的窗口,Slide较小,窗口的个数会很多。Slide小于窗口的Size时,相邻窗口会重叠,一个事件会被分配到多个窗口;Slide大于Size,有些事件可能被丢掉

基于时间的滚动窗口
//基于时间驱动,每隔5s计算一下最近10s的数据
// WindowedStream<Tuple2<String, Integer>, Tuple, TimeWindow> timeWindow =
keyedStream.timeWindow(Time.seconds(10), Time.seconds(5));
SingleOutputStreamOperator<String> applyed = countWindow.apply(new WindowFunction<Tuple3<String, String, String>, String, String, GlobalWindow>() {
@Override
public void apply(String s, GlobalWindow window, Iterable<Tuple3<String, String, String>> input, Collector<String> out) throws Exception {
Iterator<Tuple3<String, String, String>> iterator = input.iterator();
StringBuilder sb = new StringBuilder();
while (iterator.hasNext()) {
Tuple3<String, String, String> next = iterator.next();
sb.append(next.f0 + ".." + next.f1 + ".." + next.f2);
}
// window.
out.collect(sb.toString());
}
});
基于事件的滚动窗口
/**
* 滑动窗口:窗口可重叠
* 1、基于时间驱动
* 2、基于事件驱动
*/
WindowedStream<Tuple3<String, String, String>, String, GlobalWindow> countWindow = keybyed.countWindow(3,2);
SingleOutputStreamOperator<String> applyed = countWindow.apply(new WindowFunction<Tuple3<String, String, String>, String, String, GlobalWindow>() {
@Override
public void apply(String s, GlobalWindow window, Iterable<Tuple3<String, String, String>> input, Collector<String> out) throws Exception {
Iterator<Tuple3<String, String, String>> iterator = input.iterator();
StringBuilder sb = new StringBuilder();
while (iterator.hasNext()) {
Tuple3<String, String, String> next = iterator.next();
sb.append(next.f0 + ".." + next.f1 + ".." + next.f2);
}
// window.
out.collect(sb.toString());
}
});
会话时间窗口
由一系列事件组合一个指定时间长度的timeout间隙组成,类似于web应用的session,也就是一段时间没有接收到新数据就会生成新的窗口,在这种模式下,窗口的长度是可变的,每个窗口的开始和结束时间并不是确定的。我们可以设置定长的Session gap,也可以使用SessionWindowTimeGapExtractor动态地确定Session gap的长度。
val input: DataStream[T] = ...
// event-time session windows with static gap
input
.keyBy(...)
.window(EventTimeSessionWindows.withGap(Time.minutes(10)))
.<window function>(...)
// event-time session windows with dynamic gap
input
.keyBy(...)
.window(EventTimeSessionWindows.withDynamicGap(new SessionWindowTimeGapExtractor[T] {
override def extract(element: T): Long = {
// determine and return session gap
}
}))
.<window function>(...)
// processing-time session windows with static gap
input
.keyBy(...)
.window(ProcessingTimeSessionWindows.withGap(Time.minutes(10)))
.<window function>(...)
// processing-time session windows with dynamic gap
input
.keyBy(...)
.window(DynamicProcessingTimeSessionWindows.withDynamicGap(new SessionWindowTimeGapExtractor[T] {
override def extract(element: T): Long = {
// determine and return session gap
}
}))
.<window function>(...)
窗口函数
在窗口划分完毕后,就是要对窗口内的数据进行处理,一是增量计算对应reduce 和aggregate,二是全量计算对应process ,增量计算指的是窗口保存一份中间数据,每流入一个新元素,新元素与中间数据两两合一,生成新的中间数据,再保存到窗口中。全量计算指的是窗口先缓存该窗口所有元素,等到触发条件后对窗口内的全量元素执行计算
参考
https://cloud.tencent.com/developer/article/1584926
吴邪,小三爷,混迹于后台,大数据,人工智能领域的小菜鸟。
更多请关注

大数据开发-Flink-窗口全解析的更多相关文章
- 拼多多大数据开发工程师SQL实战解析
不久前,裸考国内知名电商平台拼多多的大数据岗位在线笔试,问答题(写SQL)被虐的很惨,完了下来默默学习一波.顺便借此机会复习一下SQL语句的用法. 本文主要涉及到的SQL知识点包括CREATE创建数据 ...
- BAT推荐免费下载JAVA转型大数据开发全链路教程(视频+源码)价值19880元
如今随着环境的改变,物联网.AI.大数据.人工智能等,是未来的大趋势,而大数据是这些基石,万物互联,机器学习都是大数据应用场景! 为什么要学习大数据?我们JAVA到底要不要转型大数据? 好比问一个程序 ...
- 大数据开发实战:Stream SQL实时开发一
1.流计算SQL原理和架构 流计算SQL通常是一个类SQL的声明式语言,主要用于对流式数据(Streams)的持续性查询,目的是在常见流计算平台和框架(如Storm.Spark Streaming.F ...
- 大数据开发实战:Stream SQL实时开发二
1.介绍 本节主要利用Stream SQL进行实时开发实战,回顾Beam的API和Hadoop MapReduce的API,会发现Google将实际业务对数据的各种操作进行了抽象,多变的数据需求抽象为 ...
- 从 Airflow 到 Apache DolphinScheduler,有赞大数据开发平台的调度系统演进
点击上方 蓝字关注我们 作者 | 宋哲琦 ✎ 编 者 按 在不久前的 Apache DolphinScheduler Meetup 2021 上,有赞大数据开发平台负责人 宋哲琦 带来了平台调度系统 ...
- 2019春招——Vivo大数据开发工程师面经
Vvio总共就一轮技术面+一轮HR面,技术面总体而言,比较宽泛,比较看中基础,面试的全程没有涉及简历上的东西(都准备好跟他扯项目了,感觉是抽取的题库...)具体内容如下: 1.熟悉Hadoop哪些组件 ...
- 大数据开发实战:HDFS和MapReduce优缺点分析
一. HDFS和MapReduce优缺点 1.HDFS的优势 HDFS的英文全称是 Hadoop Distributed File System,即Hadoop分布式文件系统,它是Hadoop的核心子 ...
- 大数据开发实战:Stream SQL实时开发三
4.聚合操作 4.1.group by 操作 group by操作是实际业务场景(如实时报表.实时大屏等)中使用最为频繁的操作.通常实时聚合的主要源头数据流不会包含丰富的上下文信息,而是经常需要实时关 ...
- 大数据开发实战:Spark Streaming流计算开发
1.背景介绍 Storm以及离线数据平台的MapReduce和Hive构成了Hadoop生态对实时和离线数据处理的一套完整处理解决方案.除了此套解决方案之外,还有一种非常流行的而且完整的离线和 实时数 ...
随机推荐
- 干货满满 AppGallery Connect研习社·直播深度解析优质应用开发流程
- JAVAEE_Servlet_18_关于Servlet线程安全问题
关于Servlet线程安全问题 Servlet线程安全 Servlet 是单实例多线程的环境下运行的. 在服务器运行期间,一个Servlet接口实现类,只能创建一个实例对象(一个进程(Servlet接 ...
- Day06_27_多态
多态 最关键一句话: 父类引用 指向(=) 子类对象 Animal a = new Cat(); 什么是多态? 官方说: 接口的多种不同的实现方式即为多态. 多态性是允许你将父对象设置成为一个或更多的 ...
- JDK8新特性(一) Lambda表达式及相关特性
函数式接口 函数式接口是1.8中的新特性,他不属于新语法,更像是一种规范 面向对象接口复习 在这里先回顾一下面向对象的接口,创建接口的关键字为interface,这里创建一个日志接口: public ...
- 硬件篇-04-SLAM移动底盘机械设计
这篇比较水,发出来主要是为了呼应专栏主题,既然是实现,那各个方面都得讲一下不是. 底盘SW模型 淘的,主要是看上了它有弹簧阻尼器,适合野外,抗震,但是这种底盘结构转向起来比较吃力.是再有个全轮 ...
- linux下python调用.so文件
前言 使用python 调用Fanuc的动态链路库.so 文件读取数据 环境要求 环境 需求 ubuntu16.04 32位 python3.5 32位 配置 把so文件添加到默认路径 ln -s / ...
- pyqt5 多线程+定时器+读取本地图片
前言 一个程序界面有多个button 按钮时,单击一个按钮,若此按钮对应的信号正在执行,且还未执行完毕: 此时再次单击另外一个按钮,就会出现假死状态. 这个时候我们就需要使用 多线程去解决 多线程+定 ...
- UVA11100旅行(大包装小包,问最少多少个包)
题意: 有n个包裹,每个包裹的大小都给出了,然后小的包裹可以装到大的包裹里,问最少装成多少个包裹,装成最小的包裹后还有一个限制就是让包裹数最多的那个包裹最少,就是说尽量都平均分,比如有6 ...
- node-Get&POST
Node.js GET/POST请求 var http = require('http'); var url = require('url'); var util = require('util'); ...
- 前端Excel表格导入导出,包括合并单元格,表格自定义样式等
表格数据导入 读取导入Excel表格数据这里采用的是 xlsx 插件 npm i xlsx 读取excel需要通过 XLSX.read(data, {type: type}) 方法来实现,返回一个叫W ...