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

98 阅读3分钟

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

本节课由本超大神来讲解Window计算的相关原理、类型、例子等等。

重要概念

  • 实时计算:处理时间和事件时间
  • Watermark image.png 标记当前时间,可以用来在乱序容忍和实时性之间做一个平衡。

细说Watermark

是什么

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

如何产生

原理:事件时间减去设定秒数

虽然简单,但能满足大部分业务需求

  • SQL image.png
  • DateStream image.png

如何传递

取上游数值的 最小值 作为当前数值

image.png

如何观察Watermark是否正常?(业务场景:有数据输入,没有数据输出)

  • 观察时间戳是否正常(上游数据不足或异常)
  • 展开算子,查看运行库的watermark数值

典型问题

策划选择:per-partition vs per-subtask watermark

前者 当一个subtask消费多个partition,数据读取可能会加剧乱序程度。 后者(如其名) 能有效避免该问题

部分partition/subtask断流

  • 断流含义:watermark值不更新
  • 解决方案:设置idle状态位,下游忽略被标记为idle的watermark

处理迟到数据

  • Window聚合、CEP:默认丢弃
  • 双流join中的outer join:默认不能join到任何数据

关于Window

分类

典型:

tumble(滚动)

image.png 按用户划分,如图中有14个窗口。每条数据只属于一个窗口,数据进来就会计算,但数据输出是在窗口结束才一次性输出。

sliding(滑动)

image.png 与tumble的区别:单条数据可能会属于多个窗口

session(会话)

image.png

与前两个的区别:窗口划分是动态的,多个窗口可以合并

其他:

image.png

使用例子

  • SQL
  • DataStream image.png

典型问题处理

处理迟到数据

  • 产生条件:事件时间下
  • 处理原则:丢弃
  • 具体方法:
    • 允许延迟(allow lateness): 保留原有状态的计算结果allowLateness这么长的时间,如果过程中还有原来的数据到来,则按原来的状态计算。
    • Sideoutput 标记出迟到数据,并另外捕获该数据流,根据业务需求自行处理。

增量计算和全量计算

  • 增量计算:如流计算中的sum;reduce()、aggregate()、SQL中的所有聚合
  • 全量计算:保留所有数据

EMIT触发

含义

提前输出窗口结果

实现

  • DataStream中自定义Trigger
  • SQL中进行以下配置:

image.png

高级优化

mini-batch(解决频繁状态访问)

有演进过程。

基础版本能跑,在实际应用上拓扑比较复杂,延迟增加。

进阶版本会配合watermark、checkpoint等一起使用。

local-global(倾斜优化)

image.png

Distinct计算状态复用(降低状态量)

image.png

Pane优化(降低滑动窗口状态存储量)

将单个窗口拆分成更小的pane,便于计算,输出结果时再将相应pane组合起来

案例分析

使用Flink SQL 计算日活曲线

思路:滑动窗口+EMIT触发

缺点:思路简单但不现实(所有数据都需要在一个subtask中完成窗口计算,无法并行)

改进:

1.通过两阶段聚合把数据打散

2.第二阶段聚合求和

image.png

event_time是字节内部做的一个拓展

使用Flink SQL 计算大数据任务的资源使用

通过会话窗口将数据分到一个window中并求和

image.png