36、Flink 的窗口分配器(Assigner)详解

Window Assigners
a)概述

Window assigner 定义了 stream 中的元素如何被分发到各个窗口,可以在 window(...)(用于 keyed streams)或 windowAll(...) (用于 non-keyed streams)中指定一个 WindowAssigner

WindowAssigner 负责将 stream 中的每个数据分发到一个或多个窗口中,Flink 提供了默认的 window assigner,即 tumbling windowssliding windowssession windowsglobal windows ;也可以继承 WindowAssigner 类来实现自定义的 window assigner。

所有内置的 window assigner(除了 global window)都是基于时间分发数据的,processing time 或 event time 均可。

基于时间的窗口用 start timestamp (包含)和 end timestamp (不包含)描述窗口的大小;在代码中,Flink 处理基于时间的窗口使用的是 TimeWindow, 它有查询开始和结束的 timestamp 以及返回窗口所能储存的最大 timestamp 的方法 maxTimestamp()

下图展示了每种 assigner 如何工作,紫色的圆圈代表 stream 中按 key 划分的元素(本例中是按 user 1user 2user 3 划分),x 轴表示时间的进展。

b)滚动窗口(Tumbling Windows)

滚动窗口的 assigner 分发元素到指定大小的窗口,滚动窗口的大小是固定的,且各自范围之间不重叠;如果指定了滚动窗口的大小为 5 分钟,那么每 5 分钟就会有一个窗口被计算,且一个新的窗口被创建。

DataStream<T> input = ...;

// 滚动 event-time 窗口
input
    .keyBy(<key selector>)
    .window(TumblingEventTimeWindows.of(Time.seconds(5)))
    .<windowed transformation>(<window function>);

// 滚动 processing-time 窗口
input
    .keyBy(<key selector>)
    .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
    .<windowed transformation>(<window function>);

// 长度为一天的滚动 event-time 窗口, 偏移量为 -8 小时。
input
    .keyBy(<key selector>)
    .window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(-8)))
    .<windowed transformation>(<window function>);

时间间隔可以用 Time.milliseconds(x)Time.seconds(x)Time.minutes(x) 等来指定。

如上一个例子所示,滚动窗口的 assigners 也可以传入可选的 offset 参数 ,这个参数可以用来对齐窗口。 比如说,不设置 offset 时,长度为一小时的滚动窗口会与 linux 的 epoch 对齐,会得到如 1:00:00.000 - 1:59:59.9992:00:00.000 - 2:59:59.999 等。

如果想改变对齐方式,可以设置一个 offset,如果设置了 15 分钟的 offset, 会得到 1:15:00.000 - 2:14:59.9992:15:00.000 - 3:14:59.999 等,一个重要的 offset 用例是根据 UTC-0 调整窗口的时差,在中国可能会设置 offset 为 Time.hours(-8)

c)滑动窗口(Sliding Windows)

与滚动窗口类似,滑动窗口的 assigner 分发元素到指定大小的窗口,窗口大小通过 window size 参数设置,滑动窗口需要一个额外的滑动距离(window slide)参数来控制生成新窗口的频率;如果 slide 小于窗口大小,滑动窗口可以允许窗口重叠,此时一个元素可能会被分发到多个窗口。

举例设置了大小为 10 分钟,滑动距离 5 分钟的窗口,会在每 5 分钟得到一个新的窗口,里面包含之前 10 分钟到达的数据。

DataStream<T> input = ...;

// 滑动 event-time 窗口
input
    .keyBy(<key selector>)
    .window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
    .<windowed transformation>(<window function>);

// 滑动 processing-time 窗口
input
    .keyBy(<key selector>)
    .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
    .<windowed transformation>(<window function>);

// 滑动 processing-time 窗口,偏移量为 -8 小时
input
    .keyBy(<key selector>)
    .window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8)))
    .<windowed transformation>(<window function>);

时间间隔可以使用 Time.milliseconds(x)Time.seconds(x)Time.minutes(x) 等来指定。

同滚动窗口的 assigners 一样,也可以传入可选的 offset 参数,用来对齐窗口。

比如说,不设置 offset 时,长度为一小时、滑动距离为 30 分钟的滑动窗口会与 linux 的 epoch 对齐,会得到如 1:00:00.000 - 1:59:59.999, 1:30:00.000 - 2:29:59.999 等;如果想改变对齐方式,可以设置一个 offset。

如果设置了 15 分钟的 offset,会得到 1:15:00.000 - 2:14:59.9991:45:00.000 - 2:44:59.999 等,可以根据 UTC-0 调整窗口的时差,在中国可能会设置 offset 为 Time.hours(-8)

d)会话窗口(Session Windows)

会话窗口 的 assigner 会把数据按活跃的会话分组,与滚动窗口滑动窗口不同,会话窗口不会相互重叠,且没有固定的开始或结束时间。

会话窗口在一段时间没有收到数据之后会关闭,即在一段不活跃的间隔之后,会话窗口的 assigner 可以设置固定的会话间隔(session gap)或用 session gap extractor 函数来动态地定义多长时间算作不活跃;当超出了不活跃的时间段,当前的会话就会关闭,并且将接下来的数据分发到新的会话窗口。

DataStream<T> input = ...;

// 设置了固定间隔的 event-time 会话窗口
input
    .keyBy(<key selector>)
    .window(EventTimeSessionWindows.withGap(Time.minutes(10)))
    .<windowed transformation>(<window function>);
    
// 设置了动态间隔的 event-time 会话窗口
input
    .keyBy(<key selector>)
    .window(EventTimeSessionWindows.withDynamicGap((element) -> {
        // 决定并返回会话间隔
    }))
    .<windowed transformation>(<window function>);

// 设置了固定间隔的 processing-time session 窗口
input
    .keyBy(<key selector>)
    .window(ProcessingTimeSessionWindows.withGap(Time.minutes(10)))
    .<windowed transformation>(<window function>);
    
// 设置了动态间隔的 processing-time 会话窗口
input
    .keyBy(<key selector>)
    .window(ProcessingTimeSessionWindows.withDynamicGap((element) -> {
        // 决定并返回会话间隔
    }))
    .<windowed transformation>(<window function>);

固定间隔可以使用 Time.milliseconds(x)Time.seconds(x)Time.minutes(x) 等来设置。

动态间隔可以通过实现 SessionWindowTimeGapExtractor 接口来指定。

原理 :会话窗口并没有固定的开始或结束时间,在 Flink 内部,会话窗口的算子会为每一条数据创建一个窗口, 然后将距离不超过预设间隔的窗口合并;想要让窗口可以被合并,会话窗口需要拥有支持合并的 Trigger 和 Window Function, 比如说 ReduceFunctionAggregateFunctionProcessWindowFunction

f)全局窗口(Global Windows)

全局窗口 的 assigner 将拥有相同 key 的所有数据分发到一个全局窗口,此窗口模式仅在指定了自定义的 trigger 时有用,否则计算不会发生,因为全局窗口没有天然的终点去触发其中积累的数据。

DataStream<T> input = ...;

input
    .keyBy(<key selector>)
    .window(GlobalWindows.create())
    .<windowed transformation>(<window function>);
相关推荐
花菜回锅肉2 小时前
hadoop分布式文件系统常用命令
大数据·hadoop·分布式
Yz98763 小时前
Hive基础
大数据·linux·数据仓库·hive·hadoop·bigdata
AORO_BEIDOU4 小时前
抢抓5G机遇,AORO A23防爆手机如何直击园区巡检挑战?
大数据·5g·智能手机·信息与通信
Shaidou_Data4 小时前
信息技术引领未来:大数据治理的实践与挑战
大数据·人工智能·数据清洗·信息技术·数据治理技术
Elastic 中国社区官方博客4 小时前
开始使用 Elastic AI Assistant 进行可观察性和 Microsoft Azure OpenAI
大数据·人工智能·elasticsearch·microsoft·搜索引擎·全文检索·azure
青云交5 小时前
大数据新视界 -- 大数据大厂之 Impala 性能优化:新技术融合的无限可能(下)(12/30)
大数据·性能优化·impala·技术创新·新技术融合·电商案例·跨行业应用
weixin_442643425 小时前
FileLink跨网文件安全摆渡系统——企业数据流转的安全桥梁
大数据·网络·安全·filelink文件摆渡系统
OBOO鸥柏6 小时前
OBOO鸥柏“触摸屏广告一体机交互”亮相2024中国珠海航展
大数据·人工智能·科技·交互
我是琦琦琦琦6 小时前
flink 同步oracle11g数据表到pg库
大数据·postgresql·oracle·flink
myheartgo-on7 小时前
PySpark——Python与大数据
大数据·python·信息可视化