一、描述

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 理解流式计算中的窗口概念相关推荐

  1. 流式计算中为什么需要时间戳和WaterMark

    可能很多从机器学习/深度学习转向实时计算的人会有这样一种困惑? 我们为啥需要时间戳/WaterMark 首先,EventTime来自时间戳,以及最终构成了WaterMark,这个就不展开说了,属于基本 ...

  2. Flink流式计算从入门到实战 三

    文章目录 四.Flink DataStream API 1.Flink程序的基础运行模型 2.Environment 运行环境 3.Source 3.1 基于File的数据源 3.2 基于Socket ...

  3. Flink流式计算从入门到实战 四

    文章目录 六.Flink Table API 和Flink SQL 1.Table API和SQL是什么? 2.如何使用Table API 3.基础编程框架 3.1 创建TableEnvironmen ...

  4. Flink 流式计算在节省资源方面的简单分析

    本文由小米的王加胜同学分享,文章介绍了 Apache Flink 在小米的发展,从 Spark Streaming 迁移到 Flink ,在调度计算与调度数据.Mini batch 与 streami ...

  5. 大数据之Flink流式计算引擎

    Flink DataFlow 数据的分类 有界数据 离线的计算 效率:硬件相同的情况下:时间 无界数据 实时的计算 效率:硬件环境相同的情况下,吞吐量:数据处理的数量.延迟:结果输出的时间-数据接收的 ...

  6. 流式计算-low watermark机制

    前言 最近在学习流式计算相关的知识,在阅读了MillWheel论文,在这里对low watermark机制做一个总结与介绍. Window 实时数据流是永不停歇的,我们无法获取所有的数据并产出一个最终 ...

  7. 利用百度云流式计算进行大规模设备监控

    该案例基于百度云和百度天工的物联网技术,介绍一个通过一个流式计算的任务,监控众多在线设备的方法,仅供参考. 百度云流式计算的介绍可以参考:https://cloud.baidu.com/forum/t ...

  8. 流式计算之kafka Stream

    流式计算之kafka Stream 概念 一般流式计算会与批量计算相比较.在流式计算模型中,输入是持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算.同时,计算结果是持续输出的, ...

  9. java1.8 流式计算:利用接口的函数式编程 + 链式编程

    java1.8 流式计算:利用接口的函数式编程 + 链式编程 文章目录 java1.8 流式计算:利用接口的函数式编程 + 链式编程 1.流式计算 1)ArrayList和Stream关联的底层解析( ...

最新文章

  1. 【BZOJ-1113】海报PLA 单调栈
  2. zigbee看门狗综合实验_2.5KW风光互补发电教学实验系统,风能太阳能发电实训装置_搜狐汽车...
  3. python中time库是什么意思_python中time库的time.time()函数的作用是什么
  4. python使用指南(part1)--去重
  5. mysql 密码修改时间_Mysql修改密码的方法
  6. 初来乍到,请多指教。
  7. 以整体思维看问题:解决单页应用,系统角色请求覆盖身份唯一标识(本项目中是session_id命名的)发送请求问题
  8. Zabbix Windos agent 安装
  9. CMOS工作原理和概念
  10. Java连接wincc_WinCC中访问SQL SERVER数据库
  11. C语言解题:破损的键盘
  12. 针对三层别墅的两种无线组网方案
  13. C语言之va_list
  14. 安庆集团-冲刺日志(第三天)
  15. qq_seconds.html,qq英语名字汇总82句
  16. 如何卸载手机系统应用
  17. 我的创作纪念日-从写作到阿里云专家博主的故事
  18. 我想是我该离开九又四分之三站台的时候了
  19. pythonpassif_Python中的正则表达式可截取特殊字符之前的所有文本
  20. IB化学考什么?这些知识点请收藏

热门文章

  1. 【Linux】linux进程--进程控制:进程创建、进程终止、进程等待、进程程序替换
  2. 准备入手iPhone 4港版的必看!港行无锁版iPhone 4购买全攻略
  3. 被11整除的四位偶数c语言,位和位差-什么叫奇数位和偶数位?能被11整除的数,奇 – 手机爱问...
  4. sudo rm -rf /* 命令运行演示(管理员身份删除根目录所有文件)
  5. 美通企业日报 | 陶氏杜邦完成对新陶氏的分拆;英特尔1.17亿美元投资14家创新公司...
  6. MonoRail学习笔记三:使用方便功能强大的routing功能
  7. Docker+Ovs构建SDN网络
  8. 【Promise】入门-同步回调-异步回调-JS中的异常error处理-Promis的理解和使用-基本使用-链式调用-七个关键问题
  9. 元宇宙开发者指南【Metaverse】
  10. 51单片机定时器的原理与使用