Flink设计与实现:核心原理与源码解析
上QQ阅读APP看书,第一时间看更新

1.1.3 分布式异步快照算法

基于DataFlow模型实现的计算框架虽然能够进行大规模无界乱序数据处理并平衡好准确性、延迟程度和处理成本三者之间的关系,但在数据处理过程中,保障数据一致性同样重要,尤其对于一些数据处理要求比较高的场景。在Flink中,通过checkpoint机制可以保证数据的一致性。开启checkpoint为Exactly-Once模式时,能够保证数据不重复或不丢失。Flink中的checkpoint机制由Chandy和Lamport两位科学家提出。Lamport就是分布式系统领域无人不晓的Leslie Lamport——著名的一致性算法Paxos的作者。Chandy-Lamport算法通过抽象分布式系统模型描述了一种简单、直接但是非常有效的分布式快照算法。

1.Chandy-Lamport算法设计

分布式异步快照算法应用到流式系统中就是确定一个全局快照(global snapshot),当系统出现错误时,将各个节点根据上一次的全局快照恢复整个系统。这里的全局快照我们也可以理解为全局状态(global state)。全局状态在系统进行故障排除(failure recovery)的时候非常有用,它也是分布式计算系统中容错处理的理论基础。对于分布式系统来讲,想要获取全局状态,需要面临如下挑战与问题。

·进程节点只能记录各自的状态,即本地状态信息,通过网络传递信息,形成各个进程之间的全局状态。

·所有的进程不可能在同一时间立即精确记录各自的状态,除非它们能够获取相同的时钟,但显然各节点时钟不可能完全一致。对于普通的机器来讲,晶体振动频率是有偏差的,不存在完全同步的可能性。

·同时做到全局状态过程中持续数据计算,对于STW(Stop The World,暂停当前所有运行的线程)的做法是没有意义的。

Chandy-Lamport算法是如何解决上述问题的呢?为了定义分布式系统的全局状态,首先将分布式系统简化成有限个进程与进程的组合,也就是有向无环图,其中节点是进程,边是channel,并且这些进程运行在不同的物理机器上。分布式系统的全局状态由进程的状态和channel中的信息(message)组成,而这些信息也是分布式异步快照算法需要记录的。

图1-5所示为Chandy-Lamport算法示意图,从中可以看出,整个分布式系统的全局状态包括如下3个过程。

图1-5 Chandy-Lamport算法示意图

(1)系统中的任意一个进程发起创建快照操作

1)进程P1发起快照操作,记录进程P1的状态,同时生产一个标识信息marker。注意这里的marker和进程之间通信的信息不同。

2)将marker信息通过output channel发送给系统的其他进程,图1-5中是进程P2。

3)P1开始记录所有input channel接收到的信息并写入M1存储。

(2)系统中其他进程开始逐个创建snapshot操作

1)进程P2通过input channel C12接收P1发送的marker信息。

2)如果P2没有记录自己的进程状态,则记录当前进程状态(图1-5中用深色框表示),同时将channel C12置为空,并向output channel发送marker信息;否则,记录其他channel在收到marker之前从input channel收到的所有信息。

(3)终止并完成当前的快照操作

在所有进程都收到marker信息并记录自己的状态和channel消息后,终止整个snapshot过程。此时分布式系统本次的snapshot操作结束,等待下一次触发和执行。

2.异步屏障快照(Asynchronous Barrier Snapshotting,ABS)算法改进

2015年,Flink官方发布了一篇名为“Lightweight Asynchronous Snapshots for Distributed Dataflows”的论文,旨在改进Chandy-Lamport分布式异步快照算法。该论文主要对Chandy-Lamport算法进行了以下两个方面的改进。

·在Chandy-Lamport算法中,为了实现全局状态一致,需要停止流处理程序,直到快照完成,这会对系统性能有非常大的影响。

·每次快照的内容包含传输过程中所有的内容,导致每次快照的数据量过大,进而影响系统的整体性能。

可以看出,Chandy-Lamport算法虽然能够实现全局状态一致,但或多或少牺牲了程序的性能,因此不太适合在工程上实现。异步屏障快照算法对其进行了改造,并应用在Flink项目中,其核心思想是在input source节点插入barrier事件,替代Chandy-Lamport算法中的marker,通过控制barrier事件同步实现快照备份,最终实现Exactly-Once语义。

ABS算法是Chandy-Lamport算法的变体,只是在执行上有些差别。Flink的论文分别针对有向无环和有向有环两种计算拓扑图提出了不同的算法,后者是在前者基础上进行的修改。在实际应用,尤其是在Flink系统中,大多数数据流拓扑都是有向无环图。图1-6所示为DAG的ABS算法执行流程,具体说明如下。

·barrier事件被周期性地注入所有源节点,源节点接收到barrier后会立即对自己的状态进行快照操作,然后将barrier事件发送到下游的operator节点。

·下游的Transformation Operator从上游某个input channel接收到barrier事件后,会立刻阻塞通道,直到接收到所有上游算子对应的input channel发送的barrier事件。这实际上是barrier事件的对齐过程,operator节点完成barrier对齐操作后,会对当前算子的状态进行快照操作,并向所有下游的节点广播barrier事件。

·Sink Operator接收到barrier事件后,也会进行barrier对齐操作。在所有input channel中的barrier事件全部到达Sink节点后,Sink节点会对自己的状态进行快照操作。Sink节点完成快照操作标志着完成一次系统全局快照,即完成本次checkpoint操作。

图1-6 ABS算法流程

ABS算法对Flink中的checkpoint操作进行了系统性的描述,且在Flink项目中已经有成熟的落地实现。Chandy-Lamport算法相对比较理想化,未考虑在工业落地时全局状态获取过程中的性能问题,而ABS算法实际上是对Chandy-Lamport算法在工业项目中落地实现的补充和优化。

可以看出,Flink系统融合了非常多的设计思想和理念,这些设计理念都具有一定的前瞻性。正是由于对这些思想的应用,Flink才得以从众多大数据框架中脱颖而出。我们完全有理由相信,Flink已经具备非常强的竞争力。