Flink中的Window计算(下)|青训营笔记

194 阅读3分钟

这是我参与「第四届青训营」笔记创作活动的第六天。

window机制

Window是一种将事件按照时间等因素进行分组处理的机制

时间窗口

  • 滚动窗口:滚动窗口之间不重叠,数据按key分组
  • 滑动窗口:滑动窗口

计数窗口:依据到达元素的先后管理窗口,结果具有不确定性。

会话窗口:需设置Session Gap,超过Session Gap的时间没有新的数据流入则窗口关闭,故其大小可变。

水印是嵌在流中的常规记录,计算程序通过水印获知某个时间点已到。

样例:

DataStream<T> input = ...

// 基于Event Time的滑动窗口
input
   .keyBy(<KeySelector>)
   .window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
   .<window function>(...)

// 基于Processing Time的滑动窗口
input
   .keyBy(<KeySelector>)
   .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
   .<window function>(...)

// 在滑动窗口上设置Offset偏移
input
   .keyBy(<KeySelector>)
   .window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8)))
   .<window function>(...)

迟到数据处理

Allow lateness

设置允许迟到的时间,窗口结束后保留相应时间的状态,若有新的数据到来,则继续根据之前的状态开始计算

适用:DataStream、SQL

Sideoutput 侧输出流

为迟到数据打上tag,DataStream根据tag获取迟到数据流,业务层面自行选择处理

适用:DataStream

增量计算

每条数据到来,直接进行计算,只维护中间状态,window只存储结果

典型如:reduce、aggregate等函数

SQL的聚集函数只有增量计算

全量计算

每条数据到来,存入状态中,window触发计算时取出一起计算,如process函数

EMIT触发

EMIT指在window未结束的时候提前把部分计算结果输出

在DataStream中可以自定义trigger来实现,结果有:

  • CONTINUE 什么都不做。
  • FIRE 触发计算,但不清理
  • PURGE 清理窗口数据但不执行计算。
  • FIRE_AND_PURGE 启动计算,发送结果然后清理窗口数据。

优化

mini-batch优化 减少了数据序列化反序列化次数

通过复用底层的watermark机制,将watermark作为划分mini-batch 的依据

local-global 倾斜优化

先进行预处理,再传递给下游,以降低数据shuffle的量 主要过程是先进行一个local的aggregate,再发送到global的aggregate算子。

DISTICT 计算状态复用

对同一个字段用不同的filter来进行count distinct的计算时如果每个指标都单独用一个map来记录每条数据是否出现过,状态量会变得很大。

通过将相同字段的distinct计算用一个map的key来存储,在map的value中,用一个bit vector来实现就可以把各个状态复用到一起。如一个bigint有64位,可以表示同一个字段的64个filter。

pane优化 降低计算量

对于滑动窗口,将窗口划分成更小粒度的pane,有新的数据流入时更新其对应的pane即可,当window需要输出结果时将各pane的结果merge起来即可。

案例

抖音DAU曲线绘制

主要思路:两阶段查询:先进行一个子查询将用户按uid分入各个桶中,再统计各桶中的活跃用户数量,提高了任务的并行性。

参考文章

窗口算子的使用