这篇文章主要介绍经典的分布式快照算法——Chandy Lamport Algorithm.
引入
比如在我们上面这张图里面,我们可以很容易知晓各国领导人的当前状态,因为无论从时间上还是空间的角度而言,他们都是同步好了,也就是说我们知道了在这一时刻每个领导人的状态。
但是如果这些领导人他们各自在家,我们有该如何去获取这样一个快照呢?而且同时我们实际需要的快照会更加复杂些,比如目前领导者之前通话说的内容也需要记载。
因此我们需要一个全局的快照来记录一个全局的状态。
对于一个分布式系统而言,会有许多应用程序分布在不同的物理机上。这些应用程序进程之间的交互则是使用channel(通道),那么基于这样的一个抽象的模型,我们定义我们的全局快照如下:
1 | 一个全局快照需要记录每一个进程的本地状态(例如程序变量等)以及每一个channel的状态。 |
那么我们用这个快照的好处有哪些呢?
1 | 1.用作检查点:当出现应用程序失败时可以重启恢复 |
那么快照的生成我们需要的各个进程的同一时刻的状态,且要是全局的,但是我们怎么去保证这样一个同一时刻呢?因为存在时钟倾斜的问题,我们很难保证做到这一点,也就是说同步快照是很难做到的。
1 | 由于无法做到"同时",因此在时间差上就可能有状态的变化,任何进程接受或者发送消息或者做了 |
Chandy Lamport Algorithm
为了解决这个时钟的问题,于是我们有了这个算法。
1 | 系统模型: |
初始化快照(快照的开始点)
1 | 对于进程Pi而言,它会记录自己的状态同时也会准备一个特殊的标记消息(marker message),然 |
传播快照
1 | 对于所有的进程它会对于收到的消息做一个识别.当它发现自己收到了一个marker message就会触发快照的 |
中断快照
1 | 当所有的进程都收到了marker message后并且自己的状态也记录好了,这时就会有一个 |
算法例子
如上图时最开始的起始状系统状态,首先我们P1作为快照起始点,它会先记录自己的本地状态,如下,在记录完本地状态后就成为下图了(蓝色代表状态记录完毕)
在达到上面这个图的系统状态后,在下图当中,此时P1发送了一条marker message,同时P2也发了一条消息到通道当中。
在下图当中,此时P1就会开始记录通道的消息(发送完marker message后),而P2在收到marker message后也将这个marker message广播出去了
在上图当中P2收到了标记消息(第一次)就会记录本地状态,也会将通道C12标记为empty,同时记录C12里面滞留的消息(由于上C12上面实际上啥也没有了,所以实际没做啥),现在就变成了上面的系统状态了(蓝色区域代表都已经生成好的状态)
在上图当中,P1由于发完了标记消息后也会记录C21的消息,所以M1也被记录到状态当中,然后C21也被标记为empty
最后的结果就是上面蓝色部分整体构成一个全局的快照。
算法正确性证明
首先我们这个算法的目的是解决时钟倾斜的问题的,而实际上本算法是通过保证了一个因果一致性来另辟蹊径的。因此我们需要证明它的因果一致性。
1 | 1.如果事件发生在任意一个进程的快照之前,就称之为预快照(presnapshot),也就是 |
下面开始证明:
1 | 1.如果A和B事件都发生在同一个进程当中,那么我们无需担心在生成快照时出问题 |