Flink支持Exactly-Once级别的准确行,这是一个很高的要求,一般的高吞吐量系统只支持At-least-Once级别的。Lightweight Asynchronous Snapshots for Distributed Dataflows 这篇论文是Checkpointing 机制的理论基础,这个机制的思想来源于K.MANI CHANDY和LESLIE LAMPORT 发表的一篇分布式系统如何解决全局状态一致性问题的论文
简单说,就是分布式系统要在checkpoint位置保存系统的“快照”,这样如果系统出故障,就可以从某个checkpoint点回复。但是这里的“快照”并不是某一时刻下的系统状态,不是像拍照一样的状态,和某个时刻拍张照片不同。
如上图所示,一个流计算系统某时刻的状态,包括source的位置、计算节点的累积数据、在传输中的数据、到达保存点的数据等等。如果在某个时刻把这些数据都保存,对于大吞吐量的系统来说数据量是非常大的,保存和恢复所有变量的复杂度、占用的空间都非常大。而且实际情况是分布式系统由多个节点组成,所有节点都宕机的概率很低,某个节点偶尔会failure,如果某一个节点出错整个集群都按快照恢复,代价太大了。
Chandy-Lamport 算法
Flink的可靠性机制是基于Chandy-Lamport这个算法的思想的改进版,引入了barrier,可以在不停止整个流处理系统的前提下,保存和恢复每个subtask的snapshot,让每个节点独立地做状态保存和恢复,下面分步解释一下:
Flink的Job Manager会往所有Source的流中放入一个barrier(图中三角形),barrier包含当前checkpoint的ID。
当barrier经过一个subtask时,即表示当前这个subtask处于要触发“快照”,这个节点执行checkpoint方法将当前的state进行持久存储(另一篇文章单独介绍了Flink的状态存储机制),然后将这个barrier继续往下传递。下图中Source1和Source2就是完成了checkpoint动作,然后继续把id为2的barrier继续往下传递。
barrier对齐(Barrier Alignment):
在分布式系统中,如果一个subtask有多个上游节点,这个subtask就需要等待所有上游发来的barrier(同一个序号的)都接收到,才能表示这个subtask到达了checkpoint触发的“时刻”,开始做“快照”,否则这个节点出故障恢复时无法确定该从哪个checkpoint恢复,造成数据不准确,这就是对齐barrier。如上图中的Task1.1,他有2个上游节点,Source1和Source2,source1的checkpoint(标号为2的三角形)可能比Source2的checkpoint先到达,这种情况下Task1.1要等待Source2的checkpoint也到达后再做“快照”。
当采用严格的checkpoint机制的时候,结节因为要进行barrier对齐会有暂停,造成性能下降,Flink提供了几种容错机制,可以根据实际使用场景来选择
At-Most-Once、At-Least-Once 和 Exactly-Once
当不采用checkpoint时,每个event做多就只会被处理一次,这就是At-Most-Once。
当不开启Barrier对齐时,上图中的从Source1来的紧跟在barrier后面的数据,有可能比Source2的barrier要先到Task1.1,它会被Task1.1先处理,此时如果节点处故障需要从checkpoint处回复,数据有可能处理多次,但是满足At-Least-once。
Flink是一个分布式系统,而且同一时刻,系统中会有很多个job在执行,下图展示了并行处理的情况下,系统中的checkpoint和状态存储情况
欢迎阅读,有问题可以通过邮件kaiyuan0989爱特163.com一起探讨。