热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flink项目中Window那些事

说明:本文为《Flink大数据项目实战》学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习CSDN官网课程:Flink大数据项目实战:http:t.c

说明:本文为《Flink大数据项目实战》学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习CSDN官网课程:

Flink大数据项目实战:http://t.cn/ExrHPl9

 

啥是Window?有啥作用?

Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层引擎是一个流式引擎,在上面实现了流处理和批处理。而窗口(window)就是从 Streaming 到 Batch 的一个桥梁。Flink 提供了非常完善的窗口机制,这是Flink 最大的亮点之一(其他的亮点包括消息乱序处理,和 checkpoint 机制)。

Window是一种切割无限数据集为有限块并进行相应计算的处理手段(跟keyBy一样,也是一种分组手段,只不过同一event可能被分到多个组)。

在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户点击了我们的网页。在这种情况下,我们必须定义一个窗口,用来收集最近一分钟内的数据,并对这个窗口内的数据进行计算。

Window分类(是否kyBy决定了大分类)

Keyed Windows(在已经按照key分组的基础上(KeyedStream),再构建多任务并行window)。

Flink项目中Window那些事

Non-Keyed Windows(在未分组的DataStream上构建单任务window,并行度是1,API都带All后缀)

Flink项目中Window那些事

1.3Keyed Windows vs Non-Keyed Windows(以基于time的window为例)

Flink项目中Window那些事

1.4Window的生命周期

创建:当属于该窗口的第一个元素到达时就会创建该窗口

 

销毁:当时间(event/process time)超过窗口的结束时间戳+用户指定的延迟时(allowedLateness(

例如:对于一个每5分钟创建Tumbling Windows(即翻滚窗口)窗口,允许1分钟的时延,Flink将会在12:00到12:05这段时间内第一个元素到达时创建窗口,当watermark超过12:06时,该窗口将被移除

 

Trigger(触发器):指定了窗口函数在什么条件下可被触发,触发器还可以决定在创建和删除窗口之间的任何时间清除窗口的内容。在这种情况下,清除仅限于窗口中的元素,而不是窗口元数据。这意味着新数据仍然可以添加到该窗口中。

 例如:当窗口中的元素个数超过4个时“ 或者 ”当水印达到窗口的边界时“触发计算。

 

Window 的函数:函数里定义了应用于窗口(Window)内容的计算逻辑。

 

Evictor(驱逐者):将在触发器触发之后或者在函数被应用前后,清除窗口中的元素。

2. 窗口分配器(Window Assingers)

 

2.1Window Assinger是干啥的

当你决定stream是否keyby之后,window是没有构建的,你还需要指定一个window Assinger用于定义元素如何分配到窗口中。

 

window Assinger如何指定?

1.Keyedstream:window(WindowAssigner)

2.non-keyed streams :windowAll(WindowAssigner)

 

window Assinger的作用:负责将每个传入的元素分配给一个或多个窗口。

2.2Window小分类(Window Assinger类型)

有了window Assinger,才会创建出各种形式的window来覆盖我们所需的各种场景,所以不用过多关注window本身的分类,关注window Assinger的分类即可。

 

Count-based window:根据元素个数对数据流进行分组切片

1.Tumbling CountWindow

2.Sliding CountWindow

 

Time-based window :根据时间对数据流进行分组切片

1.Tumbling Window

2.Sliding Window

3.Session Window

 

注意:Time-based window [start,end)

2.3Tumbling Windows-翻滚窗口

定义:将数据依据固定的窗口长度对数据进行切片。

 

特点:

1.时间对齐

2.窗口长度固定

3.event无重叠

 

适用场景:BI统计(计算各个时间段的指标)。

Flink项目中Window那些事

 

对齐方式:默认是aligned with epoch(整点、整分、整秒等),可以通过offset参数改变对齐方式。

Flink项目中Window那些事

2.4Sliding Windows-滑动窗口

定义:是固定窗口的更广义的一种形式。滑动窗口由固定的窗口长度和滑动间隔组成。

 

特点:

1.时间对齐

2.窗口长度固定

3.event有重叠

 

适用场景: 监控场景,对最近一个时间段内的统计(求某接口最近5min的失败率来决定是否要报警)。

Flink项目中Window那些事

对齐方式:默认是aligned with epoch(整点、整分、整秒等),可以通过offset参数改变对齐方式。

Flink项目中Window那些事

2.5Session Windows

定义:类似于web应用 的session,即一段时间没有接受到新数据就会生成新的窗口(固定gap/gap fun)。

 

特点:

1.时间无对齐

2.event不重叠

3.没有固定开始和结束时间

 

适用场景: 线上用户行为分析。

 

Gap

1.固定gap

2.动态gap:实现SessionWindowTimeGapExtractor

 

特殊处理方式

1.session window operator为每个到达的event创建一个新窗口,如果它们之间的距离比定义的间隔更近,则将窗口合并在一起。

2.为了能够合并, session window operator需要合并触发器和合并窗口函数,例如ReduceFunction、AggregateFunction或ProcessWindowFunction

(FoldFunction不能合并)。

Flink项目中Window那些事

2.6Global Windows

定义:有相同key的所有元素分配给相同的单个全局窗口,必须指定自定义触发器否则没有任何意义。

注意:不要跟Non-keyed Window搞混,两个不同的角度。

 

使用方式:

Flink项目中Window那些事

 

Flink项目中Window那些事

2.7所有窗口盘点

Flink项目中Window那些事

Flink项目中Window那些事

2.8预定义Keyed Windows

Tumbling time window

.timeWindow(Time.seconds(30))

 

Sliding time window

.timeWindow(Time.seconds(30), Time.seconds(10))

 

Tumbling count window

.countWindow(1000)

 

Sliding count window

.countWindow(1000, 10)

 

Session window

.window(SessionWindows.withGap(Time.minutes(10)))

2.9预定义Non-Keyed Windows

Tumbling time window

.timeWindowAll(Time.seconds(30))

 

Sliding time window

.timeWindowAll(Time.seconds(30), Time.seconds(10))

 

Tumbling count window

.countWindowAll(1000)

 

Sliding count window

.countWindowAll(1000, 10)

 

Session window

.window(SessionWindows.withGap(Time.minutes(10)))

3. 窗口函数(作用在window上的Operator)

3.1盘点窗口函数们

在定义了窗口分配器之后,我们需要为每一个窗口明确的指定计算逻辑,这个就是窗口函数要做的事情,当系统决定一个窗口已经准备好执行之后,这个窗口函数将被用来处理窗口中的每一个元素(可能是分组的)。

 

谁可以作为窗口函数来使用:

Flink项目中Window那些事

特别提示:在没有专门说明的情况下,凡是带All的API就是给Non-keyed window使用的。

3.2ReduceFunction

含义:ReduceFunction定义了如何把两个输入的元素进行合并来生成相同类型的输出元素的过程,Flink使用ReduceFunction来对窗口中的元素进行增量聚合。

Flink项目中Window那些事

3.3AggregateFunction

AggregateFunction是ReduceFunction的普适版本,它需要指定三个类型:输入类型(IN)、累加器类型(ACC)和输出类型(OUT)。输入类型是输入流中的元素类型,AggregateFunction有一个方法可以将一个输入元素添加到一个累加器中。该接口还具有创建初始累加器、将两个累加器合并到一个累加器以及从累加器中提取输出(类型为OUT)的方法。

Flink项目中Window那些事

3.4FoldFunction

含义:FoldFunction指定了一个输入元素如何与一个指定输出类型的元素合并的过程,这个FoldFunction 会被每一个加入到窗口中的元素和当前的输出值增量地调用,第一个元素是与一个预定义的类型为输出类型的初始值合并。

Flink项目中Window那些事

3.5WindowFunction/AllWindowFunction(会逐步退出历史舞台)

含义:一个WindowFunction将获得一个包含了window中的所有元素迭代(Iterable),并且提供灵活性。这些带来了性能的成本和资源的消耗,因为window中的元素无法进行增量迭代,而是缓存起来直到window被认为是可以处理时为止。

 

可以跟ReduceFunction /AggregateFunction/FoldFunction结合使用(推荐用法)。

Flink项目中Window那些事

3.6ProcessWindowFunction/ProcessAllWindowFunction

含义:ProcessWindowFunction获得一个包含窗口所有元素的可迭代器,以及一个具有时间和状态信息访问权的上下文对象,这使得它比其他窗口函数提供更大的灵活性。这是以性能和资源消耗为代价的,因为元素不能增量地聚合,而是需要在内部缓冲,直到认为窗口可以处理为止。

WindowFunctionde的升级版,可以跟ReduceFunction /AggregateFunction/FoldFunction结合使用(推荐用法)。

Flink项目中Window那些事

3.7ProcessWindowFunction/ProcessAllWindowFunction与ReduceFunction混搭

含义: ProcessWindowFunction可以与ReduceFunction、AggregateFunction或FoldFunction组合,以便在元素到达窗口时增量地聚合它们。当窗口关闭时,ProcessWindowFunction将提供聚合结果。ProcessWindowFunction可以在访问附加窗口元信息的同时进行增量计算。

Flink项目中Window那些事

3.8在ProcessWindowFunction中使用每个窗口的状态

含义: ProcessWindowFunction可以与ReduceFunction、AggregateFunction或FoldFunction组合,以便在元素到达窗口时增量地聚合它们。当窗口关闭时,ProcessWindowFunction将提供聚合结果。ProcessWindowFunction可以在访问附加窗口元信息的同时进行增量计算。

Flink项目中Window那些事

4. 触发器(Triggers)

4.1什么是触发器

触发器决定了一个窗口何时可以被窗口函数处理(条件满足时触发并发出信号)。

每一个WindowAssigner都有一个默认的触发器,如果默认的触发器不能满足你的需要,你可以通过调用trigger(...)来指定一个自定义的触发器。

 

触发器有5个方法来允许触发器处理不同的事件(Trigger):

1.onElement()方法,每个元素被添加到窗口时调用。

2.onEventTime()方法,当一个已注册的事件时间计时器启动时调用。

3.onProcessingTime()方法,当一个已注册的处理时间计时器启动时调用。

4.onMerge()方法,与状态性触发器相关,当使用session window时,两个触发器对应的窗口合并时,合并两个触发器的状态。

5.clear() 相应窗口被清除时触发。

 

前三个个方法通过返回TriggerResult来决定如何对其调用事件进行操作。该操作可以是以下操作之一:

1.CONTINUE:什么也不做

2.FIRE:触发计算

3.PURGE:清除窗口中的数据

4.FIRE_AND_PURGE:触发计算并随后清除窗口中的元素

这些方法中的任何一个都可以用于为将来的操作注册ProcessingTime计时器或EventTime计时器。

4.2触发和清除(Fire and Purge)

一旦一个触发器决定一个窗口已经准备好进行处理,它将触发并返回FIRE或者FIRE_AND_PURGE。这是窗口操作发送当前窗口结果的信号,发送给一个带有ProcessWindowFunction的窗口,所有元素都被传递给ProcessWindowFunction(可能在将它们传递给回收器之后)。

信号发送给具有ReduceFunction、AggregateFunction或FoldFunction的窗口只发出它们聚合的结果。

当一个触发器触发时,它可以是FIRE或者FIRE_AND_PURGE,如果是FIRE的话,将保持window中的内容,FIRE_AND_PURGE的话会清除window的内容。默认情况下,预实现的触发器仅仅是FIRE,不会清除window的状态。

注意:清除操作仅清除window的内容,并留下潜在的窗口元信息和完整的触发器状态。

4.3默认触发器

每一个窗口分配器都有一个默认的触发器。

WindowAssigner的默认触发器覆盖了很多场景(基本够用了)。例如,所有event-time window assigner都有一个EventTimeTrigger作为默认触发器。只要水印通过窗口的末端,这个触发器就会触发。

GlobalWindow的默认触发器是永不触发的NeverTrigger。因此在使用GlobalWindow时,必须定义一个自定义触发器。

通过使用trigger()指定触发器,将覆盖WindowAssigner的默认触发器。例如,如果你为TumblingEventTimeWindows指定了CountTrigger,那么将不再根据时间的进度获得窗口触发,而只根据计数。如果希望根据时间和计数进行响应,就必须编写自己的触发器。

4.4内置和自定义触发器

Flink内置的触发器:

1.EventTimeTrigger(前面提到过) 根据由watermark衡量的Event Time进度来触发。

2.ProcessingTimeTrigger 根据处理时间来触发。

3.CountTrigger 一旦窗口中的元素个数超出了给定的限制就会触发

4.PurgingTrigger 接受另一个触发器作为参数,并将其转换为一个purging触发器(当嵌套触发器触发时,将返回FIRE_AND_PURGE类型的TriggerResult)

 

自定义触发器

1.实现Trigger

2.还再发展,未来可能会有变化

5. 驱逐器(Evictors)

5.1驱逐器的作用

Evictor是可选的,WindowAssigner默认没有Evitor。

Evictor能够在Trigger触发之后以及在应用窗口函数执行前和/或后从窗口中删除无用的元素,类似filter作用(并不不是清除数据的)。

evictBefore()包含驱逐逻辑,在窗口函数之前应用。而evictAfter()在窗口函数之后应用。在应用窗口函数之前被逐出的元素将不被窗口函数处理。

Flink项目中Window那些事

5.2内置驱逐器

内置Evictor

1.CountEvitor:在窗口中保持用户指定数量的元素,并在窗口的开始处丢弃多余的元素

2.DeltaEvitor:通过一个DeltaFunction和一个阈值,计算窗口缓存中最后一个元素和剩余的所有元素的delta值,并清除delta值大于或者等于阈值的元素

3.TimeEvitor:使用一个interval(毫秒数)作为参数,对于一个给定的窗口,它会找出元素中的最大时间戳max_ts,并清除时间戳小于max_tx - interval的元素。

注意:

1.指定驱逐器可以防止任何预聚合,因为在应用计算之前,窗口的所有元素都必须传递给驱逐器。

2.Flink不能保证窗口中元素的顺序。这意味着,尽管驱逐者从窗口的开头删除元素,但这些元素不一定是最先或最后到达的元素。

6. 允许延迟(Allowed Lateness)

6.1如何允许延迟

当处理event-time的window时,可能会出现元素晚到的情况(即Flink用来跟踪event-time进度的watermark已经过了元素所属窗口的最后时间,属于当前窗口的数据才到达)。

1.默认情况下,当watermark已经过了窗口的最后时间时,晚到的元素会被丢弃。

2.Flink允许为窗口操作指定一个最大允许时延, Allowed lateness指定了元素可以晚到多长时间,默认情况下是0。

3.水位线已经过了窗口最后时间后才来的元素,如果还未到窗口最后时间加时延时间,那么元素任然添加到窗口中。根据所使用的触发器,延迟但未删除的元素可能导致窗口再次触发。例如使用EventTimeTrigger时。

4.特例:在使用GlobalWindows时,不会考虑延迟数据,因为全局窗口的结束时间戳是Long.MAX_VALUE。

6.2使用side output获取延迟的数据

当处理event-time的window时,可能会出现元素晚到的情况(即Flink用来跟踪event-time进度的watermark已经过了元素所属窗口的最后时间,属于当前窗口的数据才到达)。

Flink项目中Window那些事

6.3晚到元素注意事项

当指定允许的延迟大于0时,watermark通过窗口的末尾之后,窗口及其内容将保持不变。在这些情况下,当一个迟到但未删除的元素到达时,它可能触发窗口的另一个触发。

这些触发称为延迟触发,因为它们是由延迟事件触发的,而主触发是窗口的第一次触发。对于session window,延迟触发可能进一步导致窗口合并,因为它们可能“桥接”两个已存在的未合并窗口之间的差距。

特别注意:延迟触发发出的元素应该被视为以前计算的更新结果,即您的数据流将包含相同计算的多个结果。需要自行考虑【幂等性】问题。

 7.使用window result

7.1窗口化操作的结果

数据从WindowedStream/AllWindowedStream → (转换为)DataStream。

Window result结果元素中不保留关于窗口化操作的信息(可以在ProcessWindowFunction自己编码处理)。

Window result结果元素的timestamp=窗口允许的max timestamp = end timestamp – 1。

7.2Watermark与window的交互

watermark到达window operator时触发两件事:

1.当最大时间戳(end timestamp - 1)小于新watermark时, watermark将触发所有窗口的计算。

2.watermark原样转发给下游。

 

案例:连续的窗口操作

Flink项目中Window那些事

本实例首先根据key进行partition,然后再按指定的window对这些key进行计数,之后对该dataStream进行windowAll操作,其时间WindowAssigner与前面的相同,这样可以达到在同样的时间窗口内先partition汇总,再全局汇总的效果(可以解决类似top-k elements的问题)。

7.3估算窗口计算所需存储的注意事项

大窗口会累积很大的窗口状态,占用很大的存储(例如按月)。

估算窗口计算所需存储的注意事项:

1.滚动窗口(tumbling window)为每个元素保留一个副本(一个元素只属于一个窗口); sliding window的每个元素有多个副本,因此不要创建size很大滑动步长很小的窗口(元素的副本数会膨胀)

2.ReduceFunction、AggregateFunction和FoldFunction可以显著降低存储需求,因为他们是增量聚合,且每个窗口只存储一个值。相反,仅仅使用processwindow函数就需要积累所有元素。

3.指定驱逐器可以防止任何预聚合,因为在应用计算之前,窗口的所有元素都必须传递给驱逐器。

7.4总结

Window Assigner :决定某个元素被分配到哪个/哪些窗口中去。

Trigger :触发器,触发窗口的计算或数据清除,每个Window Assigner有一个默认的Trigger。

Evictor :“驱逐者”,类似filter作用。在Trigger触发之后,window被处理前或者后,Evictor用来删除窗口中无用的元素。默认没有驱逐器。

Flink项目中Window那些事


推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
author-avatar
岁月完好
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有