首页 > 其他分享 >Flink详解系列之六--窗口机制

Flink详解系列之六--窗口机制

时间:2024-02-19 16:22:05浏览次数:20  
标签:... 触发器 keyBy 窗口 -- Flink 之六 window Time

Flink详解系列之六--窗口机制

窗口是flink处理无限流的核心,窗口将流拆分为有限大小的“桶”,我们可以在这些桶上进行计算。

1、Keyed vs Non-Keyed Windows

根据上游数据是否为Keyed Stream类型(是否将数据按照某个指定的Key进行分区),将窗口划分为Keyed Window和Non-Keyed Windows。两者的区别在于KeyStream调用相应的window()方法来指定window类型,数据会根据Key在不同的Task中并行计算,而Non-Keyed Stream需要调用WindowsAll()方法来指定window类型,所有的数据都会在一个Task进行计算,相当于没有并行。

1.1 Keyed Windows

  1. stream
  2. .keyBy(...) <- keyed versus non-keyed windows
  3. .window(...) <- required: "assigner"
  4. [.trigger(...)] <- optional: "trigger" (else default trigger)
  5. [.evictor(...)] <- optional: "evictor" (else no evictor)
  6. [.allowedLateness(...)] <- optional: "lateness" (else zero)
  7. [.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
  8. .reduce/aggregate/fold/apply() <- required: "function"
  9. [.getSideOutput(...)] <- optional: "output tag"

1.2 Non-Keyed Windows

  1. stream
  2. .windowAll(...) <- required: "assigner"
  3. [.trigger(...)] <- optional: "trigger" (else default trigger)
  4. [.evictor(...)] <- optional: "evictor" (else no evictor)
  5. [.allowedLateness(...)] <- optional: "lateness" (else zero)
  6. [.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
  7. .reduce/aggregate/fold/apply() <- required: "function"
  8. [.getSideOutput(...)] <- optional: "output tag"

2、窗口分配器

窗口分配器负责将一个事件分配给一个或多个窗口,内置窗口包括: 滚动窗口(Tumbling Windows)、滑动窗口(Sliding Windows)、会话窗口(Session Windows)、全局窗口(Global Windows),也可以通过继承WindowAssigner类来自定义窗口。

2.1 基于时间的窗口

Flink中所有的内置窗口(全局窗口除外)都有基于时间的实现,这个时间可以是事件时间(event time),也可以是处理时间(processing time)。其中,处理滚动窗口和滑动窗口的算子,在1.12版本之前使用timeWindow(),在1.12版本被标记为废弃,转而使用window()来作为窗口处理算子,这里只介绍最新版本的使用算子。

  • 滚动时间窗口(Tumbling Time Windows)
    滚动窗口将每一个事件分配给一个有特定大小的窗口,滚动窗口有固定大小,不会重叠。比如一个滚动窗口大小(window size)为5分钟。


    使用示例如下:

  1. DataStream<T> input = ...;
  2. // tumbling event-time windows
  3. input
  4. .keyBy(<key selector>)
  5. .window(TumblingEventTimeWindows.of(Time.seconds(5)))
  6. .<windowed transformation>(<window function>);
  7. // tumbling processing-time windows
  8. input
  9. .keyBy(<key selector>)
  10. .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
  11. .<windowed transformation>(<window function>);
  12. // daily tumbling event-time windows offset by -8 hours.
  13. input
  14. .keyBy(<key selector>)
  15. .window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(-8)))
  16. .<windowed transformation>(<window function>);

由于Flink默认使用的时间基准是UTC±00:00时间,在中国需要使用UTC+08:00时间,所以最后一个示例中窗口大小为1天,时间偏移量就是8小时。

  • 滑动窗口(Sliding Time Windows)
    跟滚动窗口类似,滑动窗口也是将每一个事件分配给特定大小的窗口,且窗口有固定的大小,但它有一个窗口滑动的参数,标识一个窗口滑动的频率,或者说是每隔多久窗口滑动一次。比如一个窗口的大小为10秒钟,滑动频率为5秒。


    使用示例如下:

  1. DataStream<T> input = ...;
  2. // sliding event-time windows
  3. input
  4. .keyBy(<key selector>)
  5. .window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
  6. .<windowed transformation>(<window function>);
  7. // sliding processing-time windows
  8. input
  9. .keyBy(<key selector>)
  10. .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
  11. .<windowed transformation>(<window function>);
  12. // sliding processing-time windows offset by -8 hours
  13. input
  14. .keyBy(<key selector>)
  15. .window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8)))
  16. .<windowed transformation>(<window function>);

最后一个示例,中的Time.hours(-8)含义与滚动窗口一致。从滑动窗口的使用来看,滚动窗口其实是滑动窗口的一个特例,但窗口大小和滑动间隔相等的时候,滑动窗口就是一个滚动窗口。

  • 会话窗口(Session Windows)
    会话窗口按活动的会话对事件进行分组。与滑动窗口和滚动窗口相比,会话窗口没有固定的大小,也没有固定的起止时间,它是以一段时间没有接收到事件为窗口结束条件的。会话窗口分配器可以配置成一个固定的session gap,或者定义成一个session gap提取函数,在函数中定义一个不活跃的时长,一旦这个时长结束,当前会话就结束。


    使用示例如下:

  1. DataStream<T> input = ...;
  2. // event-time session windows with static gap
  3. input
  4. .keyBy(<key selector>)
  5. .window(EventTimeSessionWindows.withGap(Time.minutes(10)))
  6. .<windowed transformation>(<window function>);
  7. // event-time session windows with dynamic gap
  8. input
  9. .keyBy(<key selector>)
  10. .window(EventTimeSessionWindows.withDynamicGap((element) -> {
  11. // determine and return session gap
  12. }))
  13. .<windowed transformation>(<window function>);
  14. // processing-time session windows with static gap
  15. input
  16. .keyBy(<key selector>)
  17. .window(ProcessingTimeSessionWindows.withGap(Time.minutes(10)))
  18. .<windowed transformation>(<window function>);
  19. // processing-time session windows with dynamic gap
  20. input
  21. .keyBy(<key selector>)
  22. .window(ProcessingTimeSessionWindows.withDynamicGap((element) -> {
  23. // determine and return session gap
  24. }))
  25. .<windowed transformation>(<window function>);

动态的会话gap需要实现SessionWindowTimeGapExtractor接口。

2.2 基于计数的窗口

基于计数的窗口是根据事件的个数来对窗口进行划分的,概念跟基于时间的滚动窗口差不多,只不过窗口大小的划分,有时间变成了事件的个数。

  • 滚动计数窗口(Tumbling Count Windows)

  1. stream
  2. .keyBy(1)
  3. .countWindow(100) \\100为事件的个数,即窗口的大小
  4. .sum(1);
  • 滑动计数窗口(Sliding Count Windows)

  1. stream
  2. .keyBy(1)
  3. .countWindow(100, 10) \\100为事件的个数,即窗口的大小,10为滑动的间隔
  4. .sum(1);

2.3 全局窗口(Global Windows)

全局窗口分配器将所有具有相同key的元素分配到同一个全局窗口中,这个窗口模式仅适用于用户还需自定义触发器的情况。否则,由于全局窗口没有一个自然的结尾,无法执行元素的聚合,将不会有计算被执行。

使用示例如下:

  1. DataStream<T> input = ...;
  2. input
  3. .keyBy(<key selector>)
  4. .window(GlobalWindows.create())
  5. .<windowed transformation>(<window function>);

3、触发器(Triggers)

触发器决定了一个窗口何时可以被窗口函数处理,每一个窗口分配器都有一个默认的触发器,如果默认的触发器不能满足你的需要,你可以通过调用trigger(...)来指定一个自定义的触发器。触发器的接口有5个方法来允许触发器处理不同的事件:

  • onElement()方法,每个元素被添加到窗口时调用
  • onEventTime()方法,当一个已注册的事件时间计时器启动时调用
  • onProcessingTime()方法,当一个已注册的处理时间计时器启动时调用
  • onMerge()方法,与状态性触发器相关,当使用会话窗口时,两个触发器对应的窗口合并时,合并两个触发器的状态。
  • 最后一个clear()方法执行任何需要清除的相应窗口

Flink有一些内置的触发器:

  • EventTimeTrigger(前面提到过)触发是根据由水印衡量的事件时间的进度来的
  • ProcessingTimeTrigger 根据处理时间来触发
  • CountTrigger 一旦窗口中的元素个数超出了给定的限制就会触发
  • PurgingTrigger 作为另一个触发器的参数并将它转换成一个清除类型
    如果你想实现一个自定义的触发器需要继承Trigger

GlobalWindow默认的触发器是NeverTrigger,是永远不会触发的,因此,如果你使用的是GlobalWindow的话,需要定义一个自定义触发器。

4、驱逐器(Evictors)

Flink的窗口模型允许指定一个除了WindowAssigner和Trigger之外的可选参数Evitor,这个可以通过调用evitor(...)方法来实现。这个驱逐器(evitor)可以在触发器触发之前或者之后清理窗口中的元素。为了达到这个目的,Evitor接口有两个方法:

  1. void evictBefore(Iterable<TimestampedValue<T>> elements, int size, W window, EvictorContext evictorContext);
  2. void evictAfter(Iterable<TimestampedValue<T>> elements, int size, W window, EvictorContext evictorContext);

注:指定一个Evitor要防止预聚合,因为窗口中的所有元素必须得在计算之前传递到驱逐器中


 

原文链接:https://blog.csdn.net/wr_java/article/details/130127046

标签:...,触发器,keyBy,窗口,--,Flink,之六,window,Time
From: https://www.cnblogs.com/sunny3158/p/18021385

相关文章

  • 存储过程分页以及参数拼接sql语句
    1.C#调用存储过程,带参数返回的功能,而且是参数化拼接,这样就可以防止sql注入System.Data.SqlClient.SqlParameter[]parameters={newSystem.Data.SqlClient.SqlParameter("@i",100),......
  • [Go] Get used to return (*SomeType, error) as function return type
    packagemainimport( "fmt" "log" "strconv" "strings")typePointstruct{ xint yint}typeLinestruct{ p1*Point p2*Point}funcgetInput()string{return`0,9->5,98,0->0,89,4->......
  • 洛谷题单指南-递推与递归-P1990 覆盖墙壁
    原题链接:https://www.luogu.com.cn/problem/P1990题意解读:用两种可旋转的形状铺满N*2的区域,求方案数,可以使用递推。解题思路:步骤1、设f[i]表示铺满i*2的区域的方案数根据要求,i*2区域最后一列有4种可能的铺法:如果采用图1铺法,则有f[i]=f[i-1]如果采用图2铺法,则有f[i]=f......
  • STM32笔记
    整理有道云笔记中,关于STM32的笔记Keil软件中map文件解析简单的说:map文件是通过编译器编译之后,集程序、数据及IO空间的一种映射文件。遇到内存越界,或者溢出的情况,可以通过map文件,去确定函数大小,入口地址等一些重要信息。我们在Keil中最常见的就是在编译之后,编译窗口会显示类......
  • [Rust] Use Impl with Struct
    useanyhow::{Result,anyhow};usestd::str::FromStr;fnget_input()->&'staticstr{return"0,9->5,98,0->0,89,4->3,42,2->2,17,0->7,46,4->2,00,9->2,93,4->1,40,0->8,85,5->8,2&q......
  • 代码随想录算法训练营第二十二天|235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树
    二叉搜索树的最近公共祖先 题目链接:235.二叉搜索树的最近公共祖先-力扣(LeetCode)思路:只要利用二叉搜索树特性,只要当前节点的值位于要求的两个节点之间,就必定是我们要找的节点。最简单的一集。classSolution{public:TreeNode*lowestCommonAncestor(TreeNode*root,......
  • 《系统科学方法概论》绪论
    写作业要从第一页写起吧?讲课要从第一个讲起吧?成人要从出生起慢慢长大吧?那么,看书也要从第一页看起吧?《系统科学方法概论》这本书听着就有意思。那就从绪论说起吧。那么,什么是系统科学?它有那些基本特征?它在今天的发展状况又如何呢?系统科学,顾名思义,即以系统为研究对象的科学,但由于......
  • OAuth1.0
    OAuth1.0的在http请求中的使用以及签名算法说明:1、在httprequestheader的Authorization中,其格式为Authorization:"OAuthoauth_consumer_key="OAuthConsumeKey",oauth_token="OAuthToken",oauth_signature_method="HMAC-SHA256",oauth_timestamp="OA......
  • requests实现模拟登录
    发送登录请求importrequestsdata={'username':'用户名','password':'密码','captcha':'3333','remember':'1','ref':'http://www.aa7a.cn/'......
  • 逻辑器件之74HC165
    HC165和HCT165是带有互补串行输出的8位并行或串行输入移位寄存器。当并行加载PL输入为LOW时,来自D0到D7输入的并行数据会异步加载到寄存器中。当PL为HIGH时,数据会从DS输入串行输入到寄存器,并且CP每个上升沿时向右移动一个位置(Q0→Q1→Q2等)。这个特性通过将Q7输出连接到下一个设备......