[源码分析] 从源码入手看 Flink Watermark 之传播过程

[源码分析] 从源码入手看 Flink Watermark 之传播过程 0x00 摘要

本文将通过源码分析,带领大家熟悉Flink Watermark 之传播过程,顺便也可以对Flink整体逻辑有一个大致把握。

0x01 总述

从静态角度讲,watermarks是实现流式计算的核心概念;从动态角度说,watermarks贯穿整个流处理程序。所以为了讲解watermarks的传播,需要对flink的很多模块/概念进行了解,涉及几乎各个阶段。我首先会讲解相关概念,然后会根据一个实例代码从以下几部分来解释:程序逻辑/计算图模型/程序执行。最后是详细Flink源码分析(略冗长,可以选择性阅读)。

0x02 相关概念

流计算被抽象成四个问题,what,where,when,how。

window解决的是where,也就是将无界数据划分成有界数据。

window的数据何时被计算是when?解决这个问题用的方式是watermark和trigger,watermark用来标记窗口的完整性。trigger用来设计窗口数据触发条件。

1. 乱序处理

乱序问题一般是和event time关联的, 对于一个流式处理系统的process time来说,是不存在乱序问题的。所以下面介绍的watermark/allowedLateness也只是在event time作为主时间才生效。

Flink中处理乱序依赖的 watermark+window+trigger,属于全局性的处理;Flink同时对于window而言,还提供了allowedLateness方法,使得更大限度的允许乱序,属于局部性的处理;

即watermark是全局的,不止针对window计算,而allowedLateness让某一个特定window函数能自己控制处理延迟数据的策略,allowedLateness是窗口函数的属性。

2. Watermark(水位线)

watermark是流式系统中主要用于解决流式系统中数据乱序问题的机制,方法是用于标记当前处理到什么水位的数据了,这意味着再早于这个水位的数据过来会被直接丢弃。这使得引擎可以自动跟踪数据中的当前事件时间,并尝试相应地清除旧状态。

Watermarking表示多长时间以前的数据将不再更新,您可以通过指定事件时间列来定义查询的Watermarking,并根据事件时间预测数据的延迟时间。也就是说每次窗口滑动之前会进行Watermarking的计算。当一组数据或新接收的数据事件时间小于Watermarking时,则该数据不会更新,在内存中就不会维护该组数据的状态。

换一种说法,阈值内的滞后数据将被聚合,但是晚于阈值到来的数据(其实际时间比watermark小)将被丢弃。

watermark和数据本身一样作为正常的消息在流中流动。

3. Trigger

Trigger 指明在哪些条件下触发window计算,基于处理数据时的时间以及事件的特定属性。一般trigger的实现是当watermark处于某种时间条件下或者窗口数据达到一定条件,窗口的数据开始计算。

每个窗口分配器都会有一个默认的Trigger。如果默认的Trigger不能满足你的需求,你可以指定一个自定义的trigger()。Flink Trigger接口有如下方法允许trigger对不同的事件做出反应:

* onElement():进入窗口的每个元素都会调用该方法。 * onEventTime():事件时间timer触发的时候被调用。 * onProcessingTime():处理时间timer触发的时候会被调用。 * onMerge():有状态的触发器相关,并在它们相应的窗口合并时合并两个触发器的状态,例如使用会话窗口。 * clear():该方法主要是执行窗口的删除操作。

每次trigger,都是要对新增的数据,相关的window进行重新计算,并输出。输出有complete, append,update三种输出模式:

Complete mode:Result Table 全量输出,也就是重新计算过的window结果都输出。意味着这种模式下,每次读了新增的input数据,output的时候会把内存中resulttable中所有window的结果都输出一遍。

Append mode (default):只有 Result Table 中新增的行才会被输出,所谓新增是指自上一次 trigger 的时候。因为只是输出新增的行,所以如果老数据有改动就不适合使用这种模式。 更新的window并不输出,否则外存里的key就重了。

Update mode:只要更新的 Row 都会被输出,相当于 Append mode 的加强版。而且是对外存中的相同key进行update,而不是append,需要外存是能kv操作的!只会输出新增和更新过的window的结果。

从上面能看出来,流式框架对于window的结果数据是存在一个 result table里的!

4. allowedLateness

Flink中借助watermark以及window和trigger来处理基于event time的乱序问题,那么如何处理“late element”呢?

也许还有人会问,out-of-order element与late element有什么区别?不都是一回事么?答案是一回事,都是为了处理乱序问题而产生的概念。要说区别,可以总结如下:

通过watermark机制来处理out-of-order的问题,属于第一层防护,属于全局性的防护,通常说的乱序问题的解决办法,就是指这类;

通过窗口上的allowedLateness机制来处理out-of-order的问题,属于第二层防护,属于特定window operator的防护,late element的问题就是指这类。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzwfyx.html