FLINK 窗口实现原理

6 篇文章 0 订阅
4 篇文章 0 订阅

FLINK 窗口原理

Flink可以将数据流切分成一个个window窗口,对窗口内的数据进行处理。 Windows是Flink流计算的核心。Flink中支持多种窗口,包括时间窗口(Time-based Window)、会话窗口(Session-based Window)、计数窗口(Count-based Window)。Flink提供了更加简单的 .timeWindow.countWindow方法,用于定义时间窗口和计数窗口。

1、时间窗口(Time Windows)

Flink支持三种时间窗口(WindowAssigner):

  • 翻滚时间窗口(tumbling time window)
    • 滚动窗口下窗口之间不重叠,且窗口长度是固定的
  • 滑动时间窗口(sliding time window)
    • Slide的大小决定了Flink以多大的频率来创建新的窗口,Slide较小,窗口的个数会很多。
    • Slide小于窗口的Size时,相邻窗口会重叠,一个事件会被分配到多个窗口;Slide大于Size,有些事件可能被丢掉
  • 会话窗口
1.1、翻滚时间窗口(tumbling time window)

翻滚窗口只会计算从当前计时开始的1分钟内的数据,当1分钟完成时输出结果。然后,从完成这一刻起开始计算1分钟内的数据,依次类推。

翻滚窗口可以用TumblingEventTimeWindowsTumblingProcessingTimeWindows创建一个基于Event TimeProcessing Time的滚动时间窗口。

窗口的长度可以用org.apache.flink.streaming.api.windowing.time.Time中的seconds、minutes、hours和days来设置。
在这里插入图片描述

1.2、滑动时间窗口(sliding time window)

滑动窗口,顾名思义,该时间窗口是滑动的

  • 窗口:需要定义窗口的大小
  • 滑动:需要定义在窗口中滑动的大小,但理论上讲滑动的大小不能超过窗口大小
  • 适用场景
    对最近一个时间段内的统计(求某接口最近5min的失败率来决定是否要报警);
    灵活;连续的波浪;比如股票交易所它是最近24小时的涨跌幅度,随时往后算随时往后划;

可以在Flink中定义1分钟的滑动窗口,每30秒滑动一次,定义如下:

stream.timeWindow(Time.minutes(1), Time.seconds(30))

在Flink源码中,用TimeWindow表示。每个TimeWindow都有一个开始时间和结束时间,表示一个左闭右开的时间段。
在这里插入图片描述
滑动窗口以一个步长(Slide)不断向前滑动,窗口的长度固定。使用时,我们要设置Slide和Size。Slide的大小决定了Flink以多大的频率来创建新的窗口,Slide较小,窗口的个数会很多。Slide小于窗口的Size时,相邻窗口会重叠,一个事件会被分配到多个窗口;Slide大于Size,有些事件可能被丢掉。

2、窗口函数

数据经过了window和WindowAssigner之后,已经被分配到不同的窗口里。
我们要通过窗口函数,在每个窗口上对窗口内的数据进行处理。
窗口函数主要分为两种,一种是增量计算,如reduce和aggregate,一种是全量计算,如process。

2.1 增量计算

增量计算指的是窗口保存一份中间数据,每流入一个新元素,新元素与中间数据两两合一,生成新的中间数据,再保存到窗口中
当数据流中的新元素流入后,ReduceFunction将中间结果和新流入数据两两合一,生成新的数据替换之前的状态数据。
AggregateFunction也是一种增量计算窗口函数,也只保存了一个中间状态数据。

public interface AggregateFunction<IN, ACC, OUT> extends Function, Serializable {
   // 在一次新的aggregate发起时,创建一个新的Accumulator,Accumulator是我们所说的中间状态数据,简称ACC
   // 这个函数一般在初始化时调用
   ACC createAccumulator();
   // 当一个新元素流入时,将新元素与状态数据ACC合并,返回状态数据ACC
   ACC add(IN value, ACC accumulator);
  
   // 将两个ACC合并
   ACC merge(ACC a, ACC b);
   // 将中间数据转成结果数据
   OUT getResult(ACC accumulator);
}

输入类型是IN,输出类型是OUT,中间状态数据是ACC,这样复杂的设计主要是为了解决输入类型、中间状态和输出类型不一致的问题,
同时ACC可以自定义,我们可以在ACC里构建我们想要的数据结构。
比如我们要计算一个窗口内某个字段的平均值,那么ACC中要保存总和以及个数,下面是一个平均值的示例:

这几个函数的工作流程如下图所示。在计算之前要创建一个新的ACC,这时ACC还没有任何实际表示意义,
当有新数据流入时,Flink会调用add方法,更新ACC,并返回最新的ACC,
ACC是一个中间状态数据。当有一些跨节点的ACC融合时,Flink会调用merge,生成新的ACC。
当所有的ACC最后融合为一个ACC后,Flink调用getResult生成结果
2.2 全量计算

全量计算指的是窗口先缓存该窗口所有元素,等到触发条件后对窗口内的全量元素执行计算。
ProcessWindowFunction要对窗口内的全量数据都缓存。
在Flink所有API中,process算子以及其对应的函数是最底层的实现,使用这些函数能够访问一些更加底层的数据,比如直接操作状态等。

ProcessWindowFunction相比AggregateFunction和ReduceFunction的应用场景更广,能解决的问题也更复杂。
ProcessWindowFunction需要将窗口中所有元素作为状态存储起来,这将占用大量的存储资源,尤其是在数据量大窗口多的场景下,使用不慎可能导致整个程序宕机。
比如,每天的数据在TB级,我们需要Slide为十分钟Size为一小时的滑动窗口,这种设置会导致窗口数量很多,而且一个元素会被复制好多份分给每个所属的窗口,这将带来巨大的内存压力。

3、触发器(Trigger)

触发器(Trigger)决定了何时启动Window Function来处理窗口中的数据以及何时将窗口内的数据清理。

增量计算窗口函数对每个新流入的数据直接进行聚合,Trigger决定了在窗口结束时将聚合结果发送出去;全量计算窗口函数需要将窗口内的元素缓存。

Trigger决定了在窗口结束时对所有元素进行计算然后将结果发送出去。每个窗口都有一个默认的Trigger。

如果我们有一些个性化的触发条件,比如窗口中遇到某些特定的元素、元素总数达到一定数量或窗口中的元素到达时满足某种特定的模式时,我们可以自定义一个Trigger。
我们甚至可以在Trigger中定义一些提前计算的逻辑,比如在Event Time语义中,虽然Watermark还未到达,但是我们可以定义提前计算输出的逻辑,以快速获取计算结果,获得更低的延迟。
触发器决定了窗口何时会被触发计算,Flink 中开发人员需要在 window 类型的操作之后才能调用 trigger 方法传入触发器定义。

Flink 中的触发器定义需要继承并实现 Trigger 接口,该接口有以下方法:

onElement(): 每个被添加到窗口中的元素都会被调用
onEventTime(): 当事件时间定时器触发时会被调用,比如watermark到达
onProcessingTime(): 当处理时间定时器触发时会被调用,比如时间周期触发
onMerge(): 当两个窗口合并时两个窗口的触发器状态将会被调动并合并
clear(): 执行需要清除相关窗口的事件

4、清除器(Evictor)

清除器(Evictor)是在WindowAssigner和Trigger的基础上的一个可选选项,用来清除一些数据。我们可以在Window Function执行前或执行后调用Evictor。

evictBefore和evictAfter分别在Window Function之前和之后被调用,窗口的所有元素被放在了Iterable<TimestampedValue>,我们要实现自己的清除逻辑。

二、Watermark–解决乱序问题

流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的,虽然大部分情况下,流到operator的数据都是按照事件产生的时间顺序来的,
但是也不排除由于网络、分布式等原因,导致乱序的产生,所谓乱序就是指Flink接收到的事件的先后顺序不是严格按照事件的Event Time顺序排列的。

三、flink应用场景实战

3.1 基于 flink 的电商用户行为数据分析

本项目基于对电商用户行为数据,选取三个方向进行分析:

  • 热门统计 利用用户的点击浏览行为,进行流量统计、近期热门商品统计等。
  • 偏好统计 利用用户的偏好行为,比如收藏、喜欢、评分等,进行用户画像分析,给出个 性化的商品推荐列表。
  • 风险控制 利用用户的常规业务行为,比如登录、下单、支付等,分析数据,对异常情况 进行报警提示。
    来源:https://gitee.com/Carlosg_admin/Flink-UserBehaviorAnalysis/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flink(Apache Flink)是一个开源的流式处理引擎,它可以在大规模数据集上进行实时和批量处理。Flink的核心思想是将数据处理与状态管理紧密结合在一起,以实现高效的流处理。 Flink的工作原理和机制可以概括为以下几个方面: 1.数据流和数据集 Flink中的数据流是指一系列经过处理的数据记录,数据流可以是无限的(例如来自传感器的数据)或有限的(例如从文件中读取的数据)。Flink中的数据集是指一组有限的数据记录,这些数据记录可以在内存或磁盘上进行处理。 2.流处理和批处理 Flink支持流式处理和批处理,其中流处理是指实时处理无限数据流,而批处理是指在有限数据集上进行的离线处理。Flink中的流处理和批处理可以共享相同的API和运行时环境,这使得在处理大数据时更加灵活。 3.状态管理 Flink中的状态是指在数据流或数据集处理过程中存储的中间结果,例如聚合结果或窗口状态。Flink提供了多种状态管理机制,例如内存状态、RocksDB状态和分布式状态,以便在处理大规模数据时管理状态。 4.数据源和数据接收器 Flink支持从各种数据源(例如Kafka、HDFS和本地文件系统)读取数据,并将处理后的数据写入各种数据接收器(例如Kafka、HDFS和数据库)。Flink还支持自定义数据源和数据接收器,以便与各种数据存储和处理系统集成。 5.任务调度和执行 Flink使用分布式任务调度器将作业分配给集群中的各个计算节点,并在这些节点上执行作业。Flink的任务调度器可以动态调整作业的并行度和资源分配,以实现更高的性能和资源利用率。 总之,Flink的工作原理和机制是通过结合流处理和批处理、状态管理、数据源和数据接收器以及任务调度和执行等多个方面来实现的,这使得Flink成为一个高效、灵活和可扩展的流处理引擎。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值