Flink中的Window | 青训营笔记

245 阅读5分钟

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

课后拓展阅读

Timely Stream Processing

Notions of Time: Event Time and Processing Time

  • 处理时间:Processing time refers to the system time of the machine that is executing the respective operation.

例如,如果应用程序在上午 9:15 开始运行,则第一个每小时处理时间窗口将包括在上午 9:15 和上午 10:00 之间处理的事件,下一个窗口将包括在上午 10:00 和上午 11:00 之间处理的事件。

处理时间是最简单的时间概念,不需要流和机器之间的协调。它提供最佳性能和最低延迟。但是,在分布式和异步环境中,处理时间并不能提供确定性,因为它容易受到记录到达系统的速度,以及记录在系统内operators之间流动的速度的影响,容易发生乱序。

  • 事件时间:Event time is the time that each individual event occurred on its producing device.

This time is typically embedded within the records before they enter Flink, and that event timestamp can be extracted from each record. Event time programs must specify how to generate Event Time Watermarks, which is the mechanism that signals progress in event time.

For example, an hourly event time window will contain all records that carry an event timestamp that falls into that hour, regardless of the order in which they arrive, or when they are processed.

Watermark

The mechanism in Flink to measure progress in event time is watermarks.(只有event time 才有 watermark)

如果基于event time构建window,但是对于late element,我们又不能无限期的等下去,必须要有个机制来保证一个特定的时间后,必须触发window去进行计算了。这个特别的机制,就是watermark。

Watermarks flow as part of the data stream and carry a timestamp t. A Watermark(t)  declares that event time has reached time t in that stream, meaning that there should be no more elements from the stream with a timestamp t’ <= t.

水印对于无序流至关重要,如下图中事件不按时间戳排序。一般来说,水印声明了直到某个时间戳的所有事件都应该已经到达。Once a watermark reaches an operator, the operator can advance its internal event time clock to the value of the watermark.

Screenshot 2022-08-31 at 7.36.17 PM.png

思考:为什么watermark对于无序的流比较重要?

在无序流中,watermark告诉operator比watermark更早(更老/时间戳更小)的事件已经到达,operator可以将内部事件时间提前到watermark的时间戳(可以触发window计算啦)。这样的话就不用苦苦等待了。

迟到数据如何处理

直接丢弃 / allowedLateness 指定允许数据延迟的时间 / sideOutputLateData 收集迟到的数据

window基本功能

window分类

  1. Tumble Window:每个key单独划分,每个数据只属于一个窗口 / Window结束时间到达的时候一次性触发
  2. Sliding Window:每个key单独划分,每个数据可能属于多个窗口 / Window结束时间到达的时候一次性触发
  3. Session Window:window大小不固定 / Window结束时间到达的时候一次性触发

迟到数据处理 只有事件时间下才会有迟到的数据。默认丢弃迟到数据

  1. Allow lateness 适用DataStream / SQL

设置一个允许迟到时间。设置后,窗口正常计算结束后不会马上清理状态,而是会多保留allow lateness这么长时间,这个时间段内如果还有数据到来,则继续之前的状态进行计算,计算之后先retract之前的数据,然后append新的数据。

window中如果开启了allow lateness其实就是在修正之前的结果。修正之前的结果就是要有一个retract的过程

  1. SideOutput 适用DataStream

对迟到数据打一个tag,然后在Datastream上根据这个tag获取迟到数据流,然后业务层面选择自行处理

窗口计算模型

  1. 增量计算

每天数据到来就直接计算,window只存储计算结果,不需要保存每一条数据

reduce / aggregate都是增量计算,SQL的聚合只有增量计算

  1. 全量计算

每条数据到来会存储到window的state中。等到window出发计算的时候,将所有数据拿出来一起计算。如果状态数据放内存里的话,会出现各种OOM等问题

EMIT触发

  1. 如果窗口比较大,一天这种,这样计算结果输出的延迟就比较高,失去了实时计算的意义
  2. EMIT输出指的是:在window没有结束的时候,提前把window计算的部分结果输出出来。

window高级优化

  • Mini-batch优化(解决:中间结果偏多,状态访问频繁)解决频繁访问状态的问题:当状态比较大的时候通常将其放在外面而不是磁盘中。放在外面的话就会面临一个序列化和反序列化的过程。/ 利用多条数据一次性读一次状态,一次性写一次状态。在上游添加一个mini batch assigner这样一个算子
  • 倾斜优化 —— local-global(解决倾斜问题):mapreduce中的combiner就是一个local,即计算中间结果的时候不需要shuffle,先局部聚合然后再发到下游全局聚合。其是一个必备的优化功能。
  • Distinct计算状态复用,降低状态量: 在SQL中经常将distinct优化成group by / 如果每一个distinct都单独存一个状态的话,那么存储的量会有点大
  • Pane 优化 降低滑动窗口的状态存储量: 滑动窗口有的一份数据存在不同的窗口中 / 将其划分成更小的粒度,这个粒度叫Pane,一条数据只处于一个Pane,但最后需要merge操作