这是我参与「第四届青训营 」笔记创作活动的的第7天
[第四届青训营笔记创作活动]
介绍四种 Flink 中对于 Window 机制的优化方法
一、Mini-Batch
Flink SQL 中的 Mini-Batch 概念与 Spark Streaming 有些类似,即微批次处理。
在默认情况下,聚合算子对摄入的每一条数据,都会执行“读取累加器状态→修改状态→写回状态”的操作。如果数据流量很大,状态操作的 overhead 也会随之增加,影响效率。开启 Mini-Batch 之后,摄入的数据会攒在算子内部的 buffer 中,达到指定的容量或时间阈值后再做聚合逻辑。这样,一批数据内的每个 key 只需要执行一次状态读写。如果 key 的量相对比较稀疏,优化效果更加明显。
未开启和开启 Mini-Batch 机制的对比示意图如下:
显然,使用 Mini-Batch 机制会导致数据处理出现一定的延迟。
二、Logical-Global
Local-Global 优化即将原先的 Aggregate 分成 Local 和 Global 两阶段聚合,类似于 MapReduce 模型中 Combine + Reduce 处理模式。第一阶段在上游节点本地攒一批数据进行聚合(localAgg),并输出这次微批的增量值(Accumulator)。第二阶段再将收到的Accumulator merge起来,得到最终的结果(globalAgg)。
Local-Global 本质上能够靠 localAgg 聚合掉倾斜的数据,从而降低 globalAgg 热点,从而提升性能。Local-Global 用于提升 SUM、COUNT、MAX、MIN 和AVG 等普通 Aggregate 性能,以及解决这些场景下的数据热点问题。
未开启和开启 Logical-Global 机制的对比示意图如下:
三、distinct 计算状态复用
在批处理引擎中,对于 distinct 的优化,可以通过把它优化成 aggregate 的方式来处理,但是在流式计算 Window 中,我们不能直接这样进行优化,否则算子就变成会下发 retract 的数据。在 Flink 中,对于 distinct 这种情况,我们可以使用一个 Filter 维护数据的计算状态,避免数据的重复计算。
开启计算状态复用机制的示意图如下:
四、Pane
可以将 Pane 理解为窗格,在 Flink 的 Sliding Windows(滑动窗口)中,一条数据可能会属于多个 Window,当 window slide 和 window size 相差过大时,会导致同一个 key 下的 Window 数量过多,这样对于状态访问频率是比较高的,而且计算量也会增加很多。
因此可以将 Window 划分为粒度更小的 Pane,对于每条新来的数据,只需要更新他所属的 Pane,当窗口需要输出结果的时候,只需要将这个窗口对应的 Pane 的结果进行 merge 即可。
开启 Pane 机制的示意图如下:
五、总结
- Mini-Batch 优化解决频繁访问状态的问题
- Logical-Global 优化解决倾斜问题
- Distinct 状态复用减少状态量计算
- Pane 优化降低滑动窗口的状态储存量