流式计算中的 Window 计算 | 青训营笔记

103 阅读4分钟

流式计算中的 Window 计算

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

概述

批式计算 vs. 流式计算

image.png

数据实时性越高,数据价值越高

批处理

T+1架构 —— 只能得到前一天的数据

image.png

小时级批处理

image.png

实时计算

image.png

可实时处理数据,无需等待

处理时间与事件时间

image.png

Watermark

image.png

Watermark

表示系统认为的当前真实的事件时间

Watermark 的传递

这个类似于上节课中介绍的Checkpoint的制作过程,传递就类似于Checkpoint的barrier

上下游task之间有数据传输关系的,上游就会将watermark传递给下游;下游收到多个上游传递过来的watermark后,默认会取其中最小值来作为自身的watermark,同时它也会将自己watermark传递给它的下游。经过整个传递过程,最终系统中每一个计算单元就都会实时的知道自身当前的watermark是多少。

image.png

map(1)与(2)传递至window后取最小值,再继续进行传递

典型问题

1. Per-subtask 生成

问题:一个subtask消费多个partition,partition之间进度不一,导致数据读取混乱

方案:Per-partition watermark image.png

2. 部分partition/subtask 断流

image.png

subtask超时后,将其置为idle,再下游计算式忽略idle

3.迟到数据处理

image.png

处理方式:

  1. Allow lateness:设置一个允许迟到的时间。在计算结束后会保留Allow lateness的时间,在此时间内到达的数据还会继续进行计算
  1. SideOutput【测输出流】:把迟到的数据转变成一个单独的流,再由用户自己来决定如何处理这部分数据(仅DataStream窗口)
  1. 直接drop掉

Window的基本功能

image.png

Flink 中的窗口划分是key级别的

TUMBLE Window (滚动窗口)

  1. 每个key单独划分窗口

  2. 每条数据只会属于一个窗口 image.png

    如图,user1、2、3单独划分窗口,故一共有14个窗口

HOP Window (滑动窗口)

  1. 每个key单独划分窗口

  2. 每条数据可能属于多个窗口(具体属于多少,取决于窗口定义的大小和滑动) image.png

    如图,假设slide【滑动】是1h的话,那size【窗口大小】就是2h,这种情况每条数据会属于2个窗口

SESSION Window (会话窗口)

  1. 每个key单独划分窗口
  2. 每条数据会单独划分为一个窗口。如果窗口之间有交集,则会对窗口进行merge image.png

窗口触发

一次性触发

当时间大于等于window end的时候,触发对应的window的输出(计算有可能提前就增量计算好了)

目前的实现是给每个window都注册一个timer,通过处理时间或者事件时间的timer来触发window的输出。

增量计算 vs 全量计算

  • 增量计算:每条数据到来后,直接参与计算,只存储计算结果(但是还不需要输出结果)

    • DataStream中的reduce/aggregate函数
    • SQL中的窗口聚合
  • 全量计算:每条数据到来后,先放到一个buffer中,这个buffer会存储到状态里,直到窗口触发输出的时候,才把所有数据拿出来统一进行计算
    • process函数

EMIT触发

在(耗时较长的)window还未结束时,提前把window计算的部分结果输出

image.png

Window的高级优化

Mini-batch

mini-batch实现,是复用了底层的watermark传输机制,通过watermark事件来作为mini-batch划分的依据。这样整个任务中不管串联的多少个算子,整个任务的延迟都是一样的,就是用户配置的delay时间。 image.png

Local-global

意义:可以降低数据shuffle的量,同时也可以缓解数据的倾斜。

过程:将原本的聚合划分成两阶段

  • 第一阶段先做一个local的聚合,这个阶段不需要数据shuffle,是直接跟在上游算子之后进行处理的
  • 第二个阶段是要对第一个阶段的结果做一个merge(如果存在没有实现merge的聚合函数,那么这个优化就不会生效)。

image.png

Distinct状态复用

把相同字段的distinct计算用一个map的key来存储,在map的value中,用一个bit vector来实现就可以把各个状态复用到一起了。 image.png

滑动窗口pane复用

问题:在滑动窗口中,每条数据到来会直接对应多个窗口进行计算和更新,计算量大

优化方法:将窗口的状态划分成更小粒度的pane,当窗口需要输出结果的时候,只需要将这个窗口对应的pane的结果merge起来就可以了。

如图,对3小时窗口、1小时滑动的情况,可以把pane设置为1h,这样每来一条数据,我们就只更新这条数据对应的pane的结果就可以了。

image.png