流计算及其中的window | 青训营笔记

82 阅读4分钟

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

流式计算概述

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

流式计算与批示计算

7ac8c9aeca994ab1be4ae1594dde242c_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.webp

批处理

批处理模型典型的数仓架构为T+1架构,即当天只能看到前一天的计算结果。通常使用Hive,Spark。

实时计算所用到的处理时间窗口

事件时间:数据产生的时间,如客户端等上报数据的时间

watermark

定义:

当前系统认为的事件时间所在的真实时间。 数据乱序时,watermark可以用来在乱序容忍和实时性之间做一个平衡。

产生

  • 从数据的事件时间来产生常见的为使用当前事件时间的时间减去一个固定的delay,来表示可以容忍多长时间的乱序。
  • SQL: WATERMARK FOR ... AS ...(order_time - INTERVAL '5') SECOND WITH ...

传递

取上游所有的subtask的最小值

相关问题

per-partition、per-subtask watermark生成

  • 在Flink里早期都是per-subtask的方式进行watermark的生成。但是如果每个source task如果有消费多个partition的情况的话,那多个partition之间的数据可能会因为消费的速度不同而最终导致数据的乱序程度增加。
  • 新版本引入了基于每个partition单独的watermark生成机制,来避免上面的问题。

有部分partition/subtask会断流

数据断流是很常见的问题,有时候是业务数据本身就有这种特点,比如白天有数据,晚上没有数据。在这种情况下,watermark默认是不会更新的,因为它要取上游subtask发来的watermark中的最小值。此时我们可以用一种IDLE状态来标记这种subtask,被标记为这种状态的subtask,我们在计算watermark的时候,可以把它先排除在外。这样就可以保证有部分partition断流的时候,watermark仍然可以继续更新。

迟到数据处理

根据算子自身来决定如何处理迟到数据。比如window对于迟到的数据,默认就是丢弃;比如双流join,对于迟到数据,可以认为是无法与之前正常数据join上。

window

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

滚动窗口

最常见的窗口类型,每条数据只会属于一个窗口。

滑动窗口

每条数据可能会属于多个窗口,key级别划分窗口,靠timer进行窗口触发输出。

会话窗口

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

迟到数据

  • watermark驱动某个窗口触发输出之后,这个窗口如果后面又来了数据,那这种情况就属于是迟到的数据。只有事件时间下才会有迟到的数据。
  • 对于迟到数据,默认处理丢弃。

增量计算&全量计算

  • 增量计算:每条数据到来后,直接参与计算(但是还不需要输出结果)
  • 全量计算:每条数据到来后,先放到一个buffer中,这个buffer会存储到状态里,直到窗口触发输出的时候,才把所有数据拿出来统一进行计算

EMIT

EMIT输出:在window没有结束的时候,提前把window计算的部分结果输出

高级优化

  • Mini-batch优化解决频繁访问的问题
  • local-global优化解决倾斜问题
  • Distinct状态复用降低状态量
  • Pane优化降低滑动窗口的状态存储量

案例

FlinkSQL计算抖音的日活曲线

  • 日活DAU:每天的去重活跃用户数
  • 问题:每5秒更新一下DAU的数值,最终获得一天的DAU变化曲线。所有数据需要在一个subtask中完成窗口计算,无法并行
  • 方法:通过两阶段聚合打散数据,第二轮聚合只需要对各个分桶的结果求和。 (从FROM中再进行多一轮。)

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

  • 问题描述:大数据任务(特指离线任务)运行时通常会有多个container启动并运行,每个container在运行结束的时候,YARN会负责将它的资源使用(CPU、内存)情况上报。一般大数据任务运行时间从几分钟到几小时不等。
  • 需求:根据YARN上报的各个container的信息,在任务结束的时候,尽快的计算出一个任务运行所消耗的总的资源。假设前后两个container结束时间差不超过10min。
  • 方法:通过会话窗口将数据划分到一个window里,然后再将结果求和。 SELECT application_id Sum(cpu_usage) as... Sum(memory_usage) as ... FROM resource_usage GROUP BY application_id, SESSION(event_time, INTERVAL '10' MINUTE)