Flink 理解流式计算中的窗口概念
一、描述
Window 是处理无限流的核心。Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层的引擎是一个流式引擎,在上面实现了流处理和批处理。
而窗口(Window)就是从Streaming 到 batch 的一个桥梁。Flink 提供了非常完善的窗口机制,这是 Flink 最大的亮点之一(其他的亮点包括消息乱序处理和 Checkpoint 机制)
二、窗口的生命周期
窗口的生命周期,就是创建和销毁。
窗口的开始时间和结束时间是基于自然时间创建的,比如指定一个5s的窗口,那么1分钟内就会创建12个窗口。
什么时候窗口会被创建?当第一个元素进入到窗口开始时间的时候,这个窗口就被创建了。
什么时候窗口会被销毁?当时间(ProcessTime、EventTime或者 IngestionTime)越过了窗口的结束时间,再加上用户自定义的窗口延迟时间(allowed lateness),窗口就会被销毁。
举个例子来说,假设我们定义了一个基于事件时间的窗口,长度是5分钟,并且允许有1分钟的延迟。
当第一个元素包含了一个12:00的事件时间进来时,Flink会创建一个12:00 到 12:05 的窗口;在水位到 12:06 的时候,会销毁这个窗口。
每个窗口都会绑定一个触发器和一个执行函数。触发器定义了何时会触发窗口的执行函数的计算
,比如在窗口元素数量大于等于4的时候,或者水位经过了窗口结束时间的时候。
另外,每个窗口可以指定 驱逐器(Evictor),它的作用是在触发器触发后,执行函数执行前,移除一些元素。
三、Keyed 和 Non-keyed Window
在定义窗口之前,首先要指定你的流是否应该被分区,使用 keyBy(…) 后,相同的 key 会被划分到不同的流里面,每个流可以被一个单独的 task 处理。如果 不使用 keyBy ,所有数据会被划分到一个窗口里,只有一个task处理,并行度是1。
四、窗口的分类和选择
在指定了数据流是否分区之后,下一步是要去指定窗口的类型。窗口分配器(window assigner)定义了元素如何划分到不同的窗口中。
对于 keyed Streams,使用 window (…) 来定义,对于 非 keyed Streams,使用 windowAll(…)来定义。
Flink 预定义了很多种窗口类型,可以满足大多数日常使用需求:tumbling windows(翻滚窗口), sliding windows(滑动窗口), session windows(会话窗口) and global windows(全局窗口)。
所有内置的窗口(除了全局窗口)都是基于时间(ProcessTime或 EventTime)的。
1、Tumbling Windows
翻滚窗口有一个固定的长度,并且不会重复。比如,下图是指定了一个5分钟的翻滚窗口的样子:
(每个窗口都不重叠,每5分钟一个窗口)
// 例子1:tumbling event-time windows
// 定义一个数据流
val input: DataStream[T] = ...
// 这里的 key selector,如果是元组的化,可以使用_._1,如果是case class 可以使用字段名来指定
input.keyBy(<key selector>)
// 指定了一个TumblingEventTimeWindows,窗口大小为5分钟.window(TumblingEventTimeWindows.of(Time.seconds(5)))
// 窗口的操作.<windowed transformation>(<window function>)// 例子2:tumbling processing-time windows
input.keyBy(<key selector>).window(TumblingProcessingTimeWindows.of(Time.seconds(5))).<windowed transformation>(<window function>)// 例子3:daily tumbling event-time windows offset by -8 hours.
//
input.keyBy(<key selector>).window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(-8))).<windowed transformation>(<window function>)
在例子3中,TumblingEventTimeWindows.of 指定了第二个参数 offset,它的作用是改变窗口的时间。
如果我们指定了一个15分钟的窗口,那么每个小时内,每个窗口的开始时间和结束时间为:
[00:00,00:15)
[00:15,00:30)
[00:30,00:45)
[00:45,01:00)
如果我们指定了一个5分钟的offset,那么每个窗口的开始时间和结束时间为:
[00:05,00:20)
[00:20,00:35)
[00:35,00:50)
[00:50,01:05)
一个实际的应用场景是,我们可以使用 offset 使我们的时区以0时区为准。比如我们生活在中国,时区是
UTC+08:00,可以指定一个 Time.hour(-8),使时间以0时区为准。
2、Slidding Windows
滑动窗口指定了两个参数,第一个参数是窗口大小,第二个参数控制了新的窗口开始的频率。
如果 滑动距离小于窗口距离的话,那么一个元素可能被分配到多个窗口中。
比如,窗口大小10分钟,每5分钟滑动一次,如下图:
val input: DataStream[T] = ...// 例子1:sliding event-time windows
input.keyBy(<key selector>).window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5))).<windowed transformation>(<window function>)// 例子2:sliding processing-time windows
input.keyBy(<key selector>).window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5))).<windowed transformation>(<window function>)// 例子3,sliding processing-time windows offset by -8 hours
input.keyBy(<key selector>).window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8))).<windowed transformation>(<window function>)
例子3中,同样指定了一个 offset 参数,用来控制窗口开始的时间。
3、Session Windows
会话窗口根据会话的间隔来把数据分配到不同的窗口。
会话窗口不重叠,没有固定的开始时间和结束时间。
比如音乐 app 听歌的场景,我们想统计一个用户在一个独立的 session 中听了多久的歌曲(如果超过15分钟没听歌,那么就是一个新的 session 了)
我们可以用 spark Streaming ,每一个小时进行一次批处理,计算用户session的数据分布,但是 spark Streaming 没有内置对 session 的支持,我们只能手工写代码来维护每个 user 的 session 状态,里面仍然会有诸多的问题。
下一次会单独写一篇文章来讨论,如何使用flink 的 session window 来实现这个问题
4、Global Windows
全局 window 把所有相同 key 的数据,放到一个 window 来,它没有自然的窗口结束时间,所以我们需要自己指定触发器
val input: DataStream[T] = ...input.keyBy(<key selector>).window(GlobalWindows.create()).<windowed transformation>(<window function>)
五、写在最后
谢谢大家的阅读,原创不易,喜欢就随手点个赞,这将是对我最大的鼓励。如果你觉得文章还不错,就关注一下我的公众号:黑科技部落。获取Flink技术文档和万款软件。
Flink 理解流式计算中的窗口概念相关推荐
- 流式计算中为什么需要时间戳和WaterMark
可能很多从机器学习/深度学习转向实时计算的人会有这样一种困惑? 我们为啥需要时间戳/WaterMark 首先,EventTime来自时间戳,以及最终构成了WaterMark,这个就不展开说了,属于基本 ...
- Flink流式计算从入门到实战 三
文章目录 四.Flink DataStream API 1.Flink程序的基础运行模型 2.Environment 运行环境 3.Source 3.1 基于File的数据源 3.2 基于Socket ...
- Flink流式计算从入门到实战 四
文章目录 六.Flink Table API 和Flink SQL 1.Table API和SQL是什么? 2.如何使用Table API 3.基础编程框架 3.1 创建TableEnvironmen ...
- Flink 流式计算在节省资源方面的简单分析
本文由小米的王加胜同学分享,文章介绍了 Apache Flink 在小米的发展,从 Spark Streaming 迁移到 Flink ,在调度计算与调度数据.Mini batch 与 streami ...
- 大数据之Flink流式计算引擎
Flink DataFlow 数据的分类 有界数据 离线的计算 效率:硬件相同的情况下:时间 无界数据 实时的计算 效率:硬件环境相同的情况下,吞吐量:数据处理的数量.延迟:结果输出的时间-数据接收的 ...
- 流式计算-low watermark机制
前言 最近在学习流式计算相关的知识,在阅读了MillWheel论文,在这里对low watermark机制做一个总结与介绍. Window 实时数据流是永不停歇的,我们无法获取所有的数据并产出一个最终 ...
- 利用百度云流式计算进行大规模设备监控
该案例基于百度云和百度天工的物联网技术,介绍一个通过一个流式计算的任务,监控众多在线设备的方法,仅供参考. 百度云流式计算的介绍可以参考:https://cloud.baidu.com/forum/t ...
- 流式计算之kafka Stream
流式计算之kafka Stream 概念 一般流式计算会与批量计算相比较.在流式计算模型中,输入是持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算.同时,计算结果是持续输出的, ...
- java1.8 流式计算:利用接口的函数式编程 + 链式编程
java1.8 流式计算:利用接口的函数式编程 + 链式编程 文章目录 java1.8 流式计算:利用接口的函数式编程 + 链式编程 1.流式计算 1)ArrayList和Stream关联的底层解析( ...
最新文章
- 【BZOJ-1113】海报PLA 单调栈
- zigbee看门狗综合实验_2.5KW风光互补发电教学实验系统,风能太阳能发电实训装置_搜狐汽车...
- python中time库是什么意思_python中time库的time.time()函数的作用是什么
- python使用指南(part1)--去重
- mysql 密码修改时间_Mysql修改密码的方法
- 初来乍到,请多指教。
- 以整体思维看问题:解决单页应用,系统角色请求覆盖身份唯一标识(本项目中是session_id命名的)发送请求问题
- Zabbix Windos agent 安装
- CMOS工作原理和概念
- Java连接wincc_WinCC中访问SQL SERVER数据库
- C语言解题:破损的键盘
- 针对三层别墅的两种无线组网方案
- C语言之va_list
- 安庆集团-冲刺日志(第三天)
- qq_seconds.html,qq英语名字汇总82句
- 如何卸载手机系统应用
- 我的创作纪念日-从写作到阿里云专家博主的故事
- 我想是我该离开九又四分之三站台的时候了
- pythonpassif_Python中的正则表达式可截取特殊字符之前的所有文本
- IB化学考什么?这些知识点请收藏
热门文章
- 【Linux】linux进程--进程控制:进程创建、进程终止、进程等待、进程程序替换
- 准备入手iPhone 4港版的必看!港行无锁版iPhone 4购买全攻略
- 被11整除的四位偶数c语言,位和位差-什么叫奇数位和偶数位?能被11整除的数,奇 – 手机爱问...
- sudo rm -rf /* 命令运行演示(管理员身份删除根目录所有文件)
- 美通企业日报 | 陶氏杜邦完成对新陶氏的分拆;英特尔1.17亿美元投资14家创新公司...
- MonoRail学习笔记三:使用方便功能强大的routing功能
- Docker+Ovs构建SDN网络
- 【Promise】入门-同步回调-异步回调-JS中的异常error处理-Promis的理解和使用-基本使用-链式调用-七个关键问题
- 元宇宙开发者指南【Metaverse】
- 51单片机定时器的原理与使用