这是我参与「第四届青训营 」笔记创作活动的的第5天
本节课由本超大神来讲解Window计算的相关原理、类型、例子等等。
重要概念
- 实时计算:处理时间和事件时间
- Watermark
标记当前时间,可以用来在乱序容忍和实时性之间做一个平衡。
细说Watermark
是什么
系统认为的 当前真实的事件时间
如何产生
原理:事件时间减去设定秒数
虽然简单,但能满足大部分业务需求
- SQL
- DateStream
如何传递
取上游数值的 最小值 作为当前数值
如何观察Watermark是否正常?(业务场景:有数据输入,没有数据输出)
- 观察时间戳是否正常(上游数据不足或异常)
- 展开算子,查看运行库的watermark数值
典型问题
策划选择:per-partition vs per-subtask watermark
前者 当一个subtask消费多个partition,数据读取可能会加剧乱序程度。 后者(如其名) 能有效避免该问题
部分partition/subtask断流
- 断流含义:watermark值不更新
- 解决方案:设置idle状态位,下游忽略被标记为idle的watermark
处理迟到数据
- Window聚合、CEP:默认丢弃
- 双流join中的outer join:默认不能join到任何数据
关于Window
分类
典型:
tumble(滚动)
按用户划分,如图中有14个窗口。每条数据只属于一个窗口,数据进来就会计算,但数据输出是在窗口结束才一次性输出。
sliding(滑动)
与tumble的区别:单条数据可能会属于多个窗口
session(会话)
与前两个的区别:窗口划分是动态的,多个窗口可以合并
其他:
使用例子
- SQL
- DataStream
典型问题处理
处理迟到数据
- 产生条件:事件时间下
- 处理原则:丢弃
- 具体方法:
- 允许延迟(allow lateness): 保留原有状态的计算结果allowLateness这么长的时间,如果过程中还有原来的数据到来,则按原来的状态计算。
- Sideoutput 标记出迟到数据,并另外捕获该数据流,根据业务需求自行处理。
增量计算和全量计算
- 增量计算:如流计算中的sum;reduce()、aggregate()、SQL中的所有聚合
- 全量计算:保留所有数据
EMIT触发
含义
提前输出窗口结果
实现
- DataStream中自定义Trigger
- SQL中进行以下配置:
高级优化
mini-batch(解决频繁状态访问)
有演进过程。
基础版本能跑,在实际应用上拓扑比较复杂,延迟增加。
进阶版本会配合watermark、checkpoint等一起使用。
local-global(倾斜优化)
Distinct计算状态复用(降低状态量)
Pane优化(降低滑动窗口状态存储量)
将单个窗口拆分成更小的pane,便于计算,输出结果时再将相应pane组合起来
案例分析
使用Flink SQL 计算日活曲线
思路:滑动窗口+EMIT触发
缺点:思路简单但不现实(所有数据都需要在一个subtask中完成窗口计算,无法并行)
改进:
1.通过两阶段聚合把数据打散
2.第二阶段聚合求和
event_time是字节内部做的一个拓展
使用Flink SQL 计算大数据任务的资源使用
通过会话窗口将数据分到一个window中并求和