Flink 窗口最全汇总

一、概念

        将要计算的数据限制一个范围,统计一个范围内的数据。将无界的数据切割成有届的数据

二、分类

1)按照驱动类型分

        (1):时间类型窗口(Time Window)

以时间点来定义窗口的开始(start time)和结束(end time),截取出来的就是某一时间段的数据

        (2):计数窗口(Count Window)

基于元素的个数来截取数据,到达固定数据就触发计算并关闭窗口

2)按窗口分配数据的规则分类

        可以划分为四类:滚动窗口、滑动窗口、会话窗口和全局窗口

        (1):滚动窗口

        有固定的大小,是对数据"均匀分片"。窗口之间没有重叠,也不会有间隔。每个数据都会被分配到一个窗口,而且只属于一个窗口。既可以基于时间,又可以基于个数。(滑动步长等于窗口大小,可以理解成是一种特殊的滑动窗口)

        (2):滑动窗口

        窗口大小是固定的,但是窗口之间并不是首尾相接的,而是可以"错开"一定的位置。定义滑动窗口要有两个参数:窗口大小和滑动步长。既可以基于时间,又可以基于个数。

        (3):会话窗口             

        基于"会话"对数据分组。只能基于时间来定义。最重要的参数就是会话的超时时间,会话窗口的长度不固定,起始时间和结束时间也不确定

        (4):全局窗口

        会把相同key的所有数据都分配到一个窗口中。这种窗口没有结束的时候,默认是不会触发计算的。需要自己定义触发器

三、窗口 API

1)  按键分区(Keyed)和非按键分区(Non-Keyed)

        按键分区的数据流KeyedStream,没有按键分区的数据流DataStream,要观察是否有keyby操作

        (1) 按键分区 keyed window

经过keyBy划分后,数据会被分成多条逻辑流,就是KeyedStream。基于KeyedStream进行窗口操作时,窗口计算会在多个并行子任务上同时执行。相同key的数据被发往同一个并行子任务。代码实现上,需要先对DataStream调用.keyBy()按键分区,然后再调用.window()定义窗口

        (2)非按键分区

如果没有进行keyby,那么原始的DataStream就不会分成多条逻辑流,这时候的窗口逻辑只能在一个task上执行,相当于并行度变成了1。代码中直接基于DataStream调用.windowAll()定义窗

2)  代码中窗口API的调用 

窗口操作主要有两个部分:窗口分配器(Window Assigners)和窗口函数(Window Functions)。 

四、窗口分配器

 1)作用

        定义数据应该被“分配”到哪个窗口。可以说,窗口分配器其实就是在指定窗口的类型

 2)方法

        通用的定义方式为.window()调用,穿入一个WindowAssigner作为参数,返回一个WindowedStream。如果时非按键分区的,直接调用WindowAll()方法,同样传入一个WindowAssigner,返回AllWindowedStream

 3)实现

        3.1 时间窗口

                3.1.1 滚动处理时间窗口

        窗口分配器由TumblingProcessingTimeWindows提供,调用他的静态方法.of(),传入一个Time类型的参数size,表示滚动窗口的大小

                3.1.2 滑动处理时间窗口

        窗口分配器由SlidingProcessingTimeWindows提供,调用他的静态方法.of(),传入两个Time类型的参数,size和slide,也就是窗口的大小和滑动的步长

                3.1.3 处理时间会话窗口 

        窗口分配器由ProcessingTimeSessionWindow提供,需要调用他的静态方法.withGap,或者.withDynamicGap()。需要传入一个Time类型的参数size,表示会话的超时时间

                3.1.4 滚动事件时间窗口 

         窗口分配器由类TumblingEventTimeWindows提供,和滚动处理时间窗口完全一致

                3.1.5 滑动事件事件窗口

        窗口分配器由SlidingEventTimeWindows提供,用法和滑动处理时间完全一致

                3.1.6 事件时间会话窗口

        窗口分配器由类EventTimeSessionWindows提供,用法和处理时间会话窗口完全一致

        3.2 计数窗口

                3.2.1 滚动计数窗口

        直接调用.countWindow,传入一个长整型的参数size,表示窗口的大小

                3.2.2 滑动计数窗口

        直接调用.countWindow,传入两个参数,表示窗口大小和步长

                3.3.3 全局窗口

        是计数窗口的底层实现,一般需要在自定义窗口时使用。他的定义是直接调用window,窗口分配器由GlobalWindows提供

五、 窗口函数

1)增量聚合

        来一条计算一条,但是并不会立即输出,当窗口触发才会输出

①:reduce

 特点       1、相同key的第一条数据来的时候,不会调用reduce方法
                2、来一条数据就会计算一次,但是不会输出
                3、 窗口触发的时候,才会输出窗口的最终计算结果

②:aggregate 

增量聚合是有三中类型的,输入类型,累加器(中间结果的类型),输出类型。aggregate可以定义三种类型,而reduce的这三种类型都为相同的,不够灵活

2)全窗口函数

        数据来了不计算,存起来,窗口触发的时候,计算并输出结果。另外,全窗口函数提供了上下文,可以拿到比如窗口的开始时间、结束时间等信息。老版本用apply方法,新版本使用process方法,new ProcessWindowFunction<输入类型,输出类型,key类型,窗口类型>

3) 增量+全窗口 

 优点:既实现了增量来一条计算一条,又实现了可以获得上下文更多信息。

 实现方式:增量聚合算子中传入两个参数,比如aggregate,传入AggregateFunction和ProcessWindowFunction。aggregate计算完的结果传入到ProcessWindowFunction,只有一条结果

六、其他API

1)触发器(Trigger)

        主要用来控制窗口什么时候触发计算。基于.window之上嗲用.trigger方法,可以传入一个自定义的窗口触发器。会通过Trigger.FIRE方法进行触发

2)移除器 (Evictor)

        主要用来定义移除某些数据的逻辑。基于WindowedStream调用.evictor()方法,可以传入一个自定义的移除器。Evictor是一个接口,不同的窗口类型都有各自预实现的移除器

七、窗口的划分及生命周期(查看源码)

        1. 点击窗口分配器进入源码

         2. 找到assignWindows方法

     进入getStaggerOffset方法,查看计算start规则

1) start

remainder计算方法:

        例如当前时间为13s,窗口大小为10s,其中offset默认是0,用当前13 % 10 = 3,remainder>0走else路线,返回13 - 3 = 10。

        总结:start最终就要取窗口长度的整数倍。eg:10s -> 20s、30s...

2) end 

end = start + 窗口长度(窗口时左闭又开的)

属于本窗口的 最大时间戳是end - 1ms(源码中定义的)

3)生命周期

创建:属于本窗口范围的第一条数据来的时候,现new的(如上图new TimeWindow)

        思考:那是否再来这个区间的数据还会new呢?

            当然不会,使用的singletonList单例集合

销毁:关窗, 时间的进展 >= 窗口的最大时间戳(end - 1ms) + 允许迟到的时间(默认为0 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值