这是我参与「第四届青训营」笔记创作活动的第4天,学习内容为《流式计算中的Window计算》,内容包括流式计算与批式计算相比的难点和挑战、实时计算中的Watermark机制、Window的基本类型和高级优化。
本节课的重点为:流式计算与批式计算的对比、Watermark机制、Window基本功能和高级优化。思维导图如下:
流式计算与批式计算对比
流式计算与批式计算
特性 | 批式计算 | 流式计算 |
---|---|---|
数据存储 | HDFS、Hive | Kafka、Pulsar |
数据时效性 | 天级别 | 分钟级别 |
准确性 | 精准 | 精准和时效性之间取舍 |
典型计算引擎 | Hive、Spark、Flink | Flink |
计算模型 | Exactly-Once | At Least Once/Exactly Once |
资源模型 | 定时调度 | 长期持有 |
主要场景 | 离线天级别数据报表 | 实时数仓、实时营销、实时风控 |
资源模型:指流式/批式使用的计算资源模型。批式计算的任务有结束,属于定时调度;流式计算需要实时处理和实时输出,对计算资源长期持有,没有释放资源的过程。
批处理、流处理与事件时间窗口
- 批处理(离线数仓):T+1架构,数据计算是天级别的,使用的计算引擎为Hive或Spark。计算时,数据是完全ready的,输入和输出是确定性的;
- 能否直接用离线数仓的架构将天级别的计算变成小时级别的计算?
- 技术上可以实现,但是有如下两个问题:
- 批计算除了计算过程之外,还有资源申请、释放等周期调度过程,调度过程本身需要资源;
- 线上数仓任务计算时间一般是几分钟到几小时不等,而且通常的数仓建模是分层的,因此要求从数据的产生到计算完成在一个小时之内,很多场景下难以做到。
- 实时计算:处理时间的窗口,数据实时流动,实时计算,窗口结束直接发送结果,不需要周期调度任务。实时计算分为处理时间和计算时间;
- 事件时间窗口:数据产生的时间的时间称为事件时间,我们处理实时计算实际上处理的是事件时间窗口,其需要
Watermark
配合来处理乱序。
实时计算中的Watermark机制
- Watermark定义:系统认为的事件时间所在的真实时间;
- Watermark的产生:当前事件时间的时间减去一个固定的delay,来表示可以可以容忍多长时间的乱序;
- Watermark的传递:类似checkpoint机制,如下图所示:
- 生产实践遇到的问题及解决办法:
- 生成方式是根据subtask还是根据分区:Per-partition;
- 部分partition/subtask断流:Idle source;
- 迟到数据处理:算子自身决定如何处理迟到的数据
Window的基本类型和高级优化
Window基本功能
三种典型的Window
- 滚动窗口:窗口划分是key级别的,根据数据时间划分到所属窗口。窗口触发:Window结束时间到达的时候一次性触发;
- 滑动窗口:每条数据可能属于多个窗口,其它同滚动窗口;
- 会话窗口:窗口划分是一个动态过程,有merge过程(两个窗口间距小于设定值时,会触发合并操作),窗口会越来越大;
其他功能
- 迟到数据处理
- 迟到数据:如果一条数据到来后划分出的window end比当前的watermark值还要小,说明这个窗口已经触发了计算,这条数据就被认为是迟到数据;
- 只有事件时间才会有迟到数据;
- 处理方式:
- 设置一个允许迟到的时间(allow lateness):SQL里retract机制保证最终一致性,而allow lateness修正的过程就是retract过程,则下游拿到的数据流就是有最终一致性的数据流;
- 侧输出流(SideOutput):迟到数据打tag,业务层面自行选择处理迟到数据。
-
增量计算和全量计算:
- 增量计算:每条数据到来直接计算----------SQL的聚合、DataStream的reduce和aggregate函数;
- 全量计算:每条数据到来先存储到window 的state中,等window触发计算时将所有数据拿出来一起计算---------------DataStream的process函数。
-
EMIT触发:在window没有结束的时候,提前把window计算的部分结果输出出来,DataStrema自定义trigger实现(FIRE)。
Window高级优化
Mini-batch优化
- 未优化前存在的问题:存储中间结果有很大开销,且对状态访问频繁程度很高,对CPU开销大;
- 解决方案(mini-batch),赞一小批数据再进行计算,这批数据每个key的state访问只有一次,这样在单个key的数据比较集中的情况下,对于状态访问可以有效的降低频率,最终提升性能;
- 实际实现:利用watermark机制,上游添加organizer算子,统一发起指令开始当前新的mini-batch,下游算子收到信号后将之前的buffer数据计算输出再往下传递信号,下游在一个上游信号周期内就可以完成整个链路所有算子的计算。
倾斜优化---local global
- 降低数据shuffle量,缓解数据倾斜;
- local global:在处理之前,不需对数据进行shuffle操作,对数据预处理把中间结果发到最终的结果处理。即 先做一个local聚合,再将聚合的结果做merge操作。
Distinct计算状态复用
- 在流式计算中,对于count distinct这种情况,我们是需要保存所有数据是否出现过,常规方法是用map存为一个映射,但如果每个指标都用一个map来记录那么状态量会很大,因此可以用位运算优化;
- key:相同字段的distinct计算;value:一个bit vector。举例:
<key:使用苹果手机的去重用户字段,value:二进制0/1表示是否使用,用vector存储,每个元素是一个64位的Int>
。
Pane优化
- 问题:滑动窗口,一条数据可能属于多个窗口。如果滑动比例太大,那么每条数据参与计算量大;
- 解决办法:将窗口划分为粒度更小的pane,每个数据只处于一个pane。每来一条数据,我们就只更新这条数据对应的pane的结果就可以了。当窗口需要输出结果的时候,只需要将这个窗口对应的pane的结果merge起来就可以了;
- 注意:这里也是需要所有聚合函数都有merge的实现的。
课程总结:
- 流式计算基本概念和批式计算的区别,直接将离线仓做实时运算有哪些困难;
- Watermark的含义、如何产生和传递以及生产实践遇到的问题和解决办法;
- 三种典型的Window和迟到数据处理、增量计算VS全量计算、EMIT输出;
- Window高级优化:Mini-batch、倾斜优化、Distinct状态复用和Pane优化。