【Flink】超详细Window机制……(下)

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 【Flink】超详细Window机制……

2.6 Window函数

  • 增量计算函数

       增量计算指的是窗口保存一份中间数据,每流入一个新元素,新元素都会与中间数据合并,生成新的中间数据,在保存到窗口中。如ReduceFunction、AggregateFunction、FoldFnction。


  • 全量计算函数

       全量计算函数指的是先缓存该窗口的所有元素,等到触发条件后对窗口内的所有元素执行计算。如ProcessWindowFunction。

三、Watermark

3.1 DataStream Watermark生成

  • Source Function中生成Watermark

       SourceFunction 可以直接为数据元素分配时间戳,同时也会向下游发送Watermark。需要注意的是:如果一个timestamp 分配器被使用的话,由源提供的任何Timestramp和Watermark都会被重写。


       为了通过SourceFunction直接为一个元素分配一个时间戳,SourceFunction需要调用SourceContext中的collectWithTimestamp(T element, long timestamp)方法。为了生成Watermark,源需要调用emitWatermark(Watermark)方法。


  • DataStreamApi 中生成Watermark

       DataStreamApi中使用的TimestampAssigner接口定义了时间戳的提取行为,其有两个不同接口AssignerWithPeriodicWatermarks和AssingerWithPunctuatedWatermarks,分别代表了不同的Watermark生成策略。


640.png


       1)AssignerWithPeriodicWatermarks是周期性生成Watermark策略的顶层抽象接口,该接口的实现类周期性地生成watermark,而不会针对每一个事件都生成。


       2)AssignerWithPunctuatedWatermarks对每一个事件都会尝试进行Watermark的生成,但是如果生成的Watermark是null或者Watermark小于之前的Watermark,则该Watermark不会发往下游,因为发往下游也不会有任何效果,不会触发任何窗口的执行。

3.2 FlinkSQL Watermark生成

        其Watermark的生成主要是在TableSource中完成的,其定义了3类Watermark生成策略。

640.png

  • 周期性Watermark策略

       PeriodicWatermarkAssigner周期性(一定时间间隔或者达到一定的记录条数)地产生一个Watermark。生产使用时,一定注意时间和数据量,结合时间和积累条数两个维度继续周期性产生Watermark,否则在极端情况下会有很大延迟。


       1)AscendingTimestamps:递增Watermark,作用在Flink SQL中的Rowtime属性上,Watermark = 当前收到的数据元素的最大时间戳 -1,此处减1的目的是确保有最大时间戳的时间不会被当做迟到的数据丢弃。


       2)BoundedOutOfOrderTimestamps:固定延迟Watermark,作用在Flink SQL的Rowtime属性上,Watermark = 当前收到的数据元素的最大时间戳-固定延迟。


  • 每个事件Watermark策略

       PuntuatedWatermarkAssigner,数据流中每一个递增的EventTime都会产生一个Watermark。在生产中,除非实时性非常高的场景下才会选择Puntuated的方式进行Watermark生成。


  • 无为策略

       PreserveWatermark,可以使用DataStream Api和Table & SQL混合编程,所以FlinkSQL中不设定Watermark策略。

3.3 多流的Watermark

       Flink内部实现每一个边上只能有一个递增的Watermark,当出现多流携带EventTime汇聚到一起(GroupBy或Union)时,Flink会选择所有流入的EventTime中最小的一个向下游流出,从而保证Watermark的单调递增和数据的完整性。


       Flink作业一般是并行执行的,作业包含多个Task,每个Task运行一个或一组算子(operator chain) 实例,Task在生成Watermark的时候是相互独立的,也就是说在作业中存在多个并行的Watermark。多流输入会被分解成多个双流输入,对于多个双流Watermark处理,无论哪一个流的Watermark进入算子,都需要跟另一个流的当前算子进行比较,选择较小的的Watermark,即Min(input1 Watermark,input2Watermark),与算子当前的Watermark比较,如果大于当前算子的Watermark,则更新算子的Watermark为新的Watermark,并发送下游。


AbstractStreamOperator.java


640.png


3.4 时间服务

  • 定时器服务器

       定时器服务器在Flink中叫作TimeService,窗口算子(WindowOperator)中使用了InternalTimerService来管理定时器(Timer),其初始化是在WindowOperator#open()内实现的。


       InternaleTimerService有几个元素比较重要:名称、命名空间类型N(及其序列化器)、键类型K(及其序列化器)和Triggerable对象(支持延时计算的算子,继承了Triggerable接口来实现回调)


       一个算子中可以有多个InternalTimeService,通过名称进行区分:


       1)WindowOperator:名称为 "window-timers"


       2)KeyedProcessOperator:名称为"user-timers"


       3)CepOperator:名称为"watermark-callbacks"


       InternalTimerService接口实现类是InternalTimerServiceImpl,Timer的实现类是InternalTimer。InternalTimeServiceImpl使用了两个TimerHeapInternalTimer的优先队列(HeapPriorityQueueSet,该优先队列是Flink自己实现的),分别用于维护事件时间和处理时间的Timer。

640.png

 InternalTimeServiceManager是Task级别提供的InternalService集中管理器。其使用Map保存了当前所有的InterTimerService,Map的key是InternalTimerService的名字。

640.png

  • 定时器

       定时器在Flink中叫作Timer。窗口的触发器与定时器是紧密联系的。

       Flink的定时器使用InternalTimer接口定义行为。

640.png

 Timer到底是如何触发然后回调用户逻辑的呢?


       在InternalTimerServiceImpl中寻找答案,对于事件时间,会根据Watermark的时间,从事件时间的定时器队列中找到比给定时间小的所有定时器 ,触发该Timer所在的算子,然后由算子去调用UDF中的onTime()方法。处理时间也是类似的逻辑,区别在于,处理时间是从处理时间Timer优先队列中找到Timer。处理时间依赖于当前系统是,所以使用的周期性调度。


640.png


  • 优先队列

       Flink在优先级队列中使用了KeyGroup,是按照KeyGroup去重的,并不是按照全局的Key去重。

640.png

Flink自己实现了优先级队列来管理Timer:


       1)基于堆内存的优先级队列HeapPriorityQueueSet:基于Java堆内存的优先级队列,其实现思路与Java的PriorityQueue类型,使用了二叉树。


       2)基于RocksDB的优先级队列:分为Cache+RocksDB量级,Cache中保存了前N个元素,其余的保存在RocksDB中。写入的时候采用Write-through策略,即写入Cache的同时要更新RocksDB中的数据,可能需要访问磁盘。


相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
24天前
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
54 3
|
29天前
|
SQL 消息中间件 分布式计算
大数据-120 - Flink Window 窗口机制-滑动时间窗口、会话窗口-基于时间驱动&基于事件驱动
大数据-120 - Flink Window 窗口机制-滑动时间窗口、会话窗口-基于时间驱动&基于事件驱动
84 0
|
29天前
|
SQL 分布式计算 大数据
大数据-119 - Flink Window总览 窗口机制-滚动时间窗口-基于时间驱动&基于事件驱动
大数据-119 - Flink Window总览 窗口机制-滚动时间窗口-基于时间驱动&基于事件驱动
57 0
|
3月前
|
SQL 存储 Unix
Flink SQL 在快手实践问题之设置 Window Offset 以调整窗口划分如何解决
Flink SQL 在快手实践问题之设置 Window Offset 以调整窗口划分如何解决
53 2
|
3月前
|
存储 数据处理 Apache
超越传统数据库:揭秘Flink状态机制,让你的数据处理效率飞升!
【8月更文挑战第26天】Apache Flink 在流处理领域以其高效实时的数据处理能力脱颖而出,其核心特色之一便是状态管理机制。不同于传统数据库依靠持久化存储及 ACID 事务确保数据一致性和可靠性,Flink 利用内存中的状态管理和分布式数据流模型实现了低延迟处理。Flink 的状态分为键控状态与非键控状态,前者依据数据键值进行状态维护,适用于键值对数据处理;后者与算子实例关联,用于所有输入数据共享的状态场景。通过 checkpointing 机制,Flink 在保障状态一致性的同时,提供了更适合流处理场景的轻量级解决方案。
55 0
|
5月前
|
消息中间件 存储 NoSQL
Flink(十二)【容错机制】(4)
Flink(十二)【容错机制】
|
5月前
|
存储 缓存 算法
Flink(十二)【容错机制】(2)
Flink(十二)【容错机制】
|
29天前
|
分布式计算 Java 大数据
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
29 0
|
29天前
|
SQL 消息中间件 分布式计算
大数据-115 - Flink DataStream Transformation 多个函数方法 FlatMap Window Aggregations Reduce
大数据-115 - Flink DataStream Transformation 多个函数方法 FlatMap Window Aggregations Reduce
35 0
|
3月前
|
SQL 安全 流计算
Flink SQL 在快手实践问题之Group Window Aggregate 中的数据倾斜问题如何解决
Flink SQL 在快手实践问题之Group Window Aggregate 中的数据倾斜问题如何解决
74 1