尝试使用Chandy-Lamport方法设计分布式数据库快照

尝试使用Chandy-Lamport方法设计分布式数据库快照

C-L理论

根据Chandy-Lamport论文中的说明,分布式系统中节点间通过消息通道传递消息,消息按照顺序发送和接收。
某个节点做过快照后,通过消息通道发送不影响系统状态的消息marker通知其它节点做快照。
一个节点接收到marker消息时,如果还没做快照,那么就做快照,记录接收消息通道为空。已经做过快照的话,就记录从做快照开始,到marker消息这段时间的接收消息通道上的消息。
考虑一个复杂的多节点分布式系统,任意两个节点之间都有收发消息的通道,就是我想要根据C-L理论设计的分布式系统。

单个数据库的快照

单个节点的数据库快照方法是比较简单的,核心思想是记录当前数据库的一个快照,这个快照中不能包含未提交的事务,并且能够根据快照和此快照后的redo日志恢复数据库。
假设数据库事务的事务号是从1开始严格递增的,快照也会有对应的事务号,假设是sxid,那么快照就包含从1开始到sxid所有事务的数据。
在数据库启动时恢复事务号为sxid的快照和sxid+1开始的redo日志就可以。

分布式数据库的快照

分布式数据库会涉及到分布式事务,分布式事务的数据与多个节点相关,快照数据要保证所有节点上的分布式事务都完整的,同时保证每个节点自己的事务都是完整的并且连续的。
假设分布式系统上的每个节点都可以发起分布式事务,可能会涉及到其它任一节点,那么根据C-L的描述,两个节点之间都会有两个单向通道。就像论文中的图片:
在这里插入图片描述

分布式事务号与本地事务号
本地事务是指仅涉及到本节点数据的事务。
分布式事务涉及到当前节点的数据,也会生成一个本地事务,那么这个事务就有一个本地事务号和分布式事务号。

2节点分布式系统

先假设只有两个节点的系统,两个节点DBa和DBb,DBa发向DBb的通道是Cab,DBb发向DBa的通道是Cba

通道描述Cxy表示DBx节点发向DBy节点的通道,下面都用这种记号。

快照的流程:

  1. DBa开始做快照,事务号XA1,分布式事务号DXA1;
  2. 通过Cab向DBb发送marker消息;
  3. DBb收到marker消息,记录自己的快照,本地事务号XB1,分布式事务号DXB1;
  4. DBb向DBa发送marker消息,DBa收到marker消息前的分布式事务号为DXA2,对应的本地事务号为XA2;
  5. DBa记录通道Cba上的消息,为[DXA1 + 1, DXA2]。

按照C-L的理论,分布式系统的快照这样就可以了。但是实际上,除了有分布式事务,还有本地事务。要得到一个完整的分布式系统快照,需要每个节点也有完整的快照。
上面描述的流程第5步,DBa记录了消息通道上的数据,但是忽略了本地事务。对DBa来说,完整的事务应该是[XA1 + 1, XA2]。
另一个问题,DBa的事务[XA1 + 1, XA2]之间,也可能会包含DBa发起的分布式事务,这一部分事务没有在DBb中记录,所以还有缺陷。
解决这个缺陷的方法很简单,可以在DBa发送marker消息后,接收到DBbmarker消息前,就不再发起分布式事务,就是不再通过通道C12发消息。
另外,消息通道上的数据,可以不记录下来,直接当做事务redo到快照中。
这样就有最终流程:

  1. DBa开始做快照,事务号XA1,分布式事务号DXA1;
  2. 通过Cab向DBb发送marker消息,block 通道C12,不再发送分布式事务消息;
  3. DBb收到marker消息,记录自己的快照,本地事务号XB1,分布式事务号DXB1;
  4. DBb向DBa发送marker消息,DBa收到marker消息前的分布式事务号为DXA2,对应的本地事务号为XA2;
  5. DBa记录通道Cba上的消息,为[DXA1 + 1, DXA2],恢复通道C12;
  6. DBa redo通道上的消息到刚才记录的快照上。

多个节点分布式系统

再进一步,假设其中有个节点是DBa,还有N个其它节点,任意两个节点之间都有双向通道。
快照一个可能的流程:

  1. DBa做快照,对另外N个节点的任一节点n,发送marker消息,block Can, 记录通道Cxa消息号DXA1n;
    对其它N个节点的任一节点DBn
    接收节点DBmmarker消息(这个消息可能不是从DBa发来的),分为两种情况:
    没有做快照
    做快照,向其它所有节点发送marker消息,记录所有发向DBn的通道消息号DXN1x(x是任意其它节点),阻塞所有发出去的通道Cnx;
    已经做了快照
    记录通道Cmn上的消息从DXN1m开始到marker消息之前,比如是DXN2m。放开通道Cnm
    问题
    对于节点DBn,记录DBx发向它的通道的事务[DXN1x + 1, DXN2x],假设对应本地事务号为[XN1x + 1, XN2x]。
    对任意的DBx,XN1x都是接收到marker消息时的事务号,所以让
    XN1x = XN1 x ∈ 任意节点除DBN
    把通道上的事务数据redo到快照上,那么所有的事务就是:
    [XN1 + 1, max(XN2x)] x ∈ 任意节点除DBN

使
XN2max = max(XN2x) x ∈ 任意节点除DBN

所有事务就是
[XN1 + 1, XN2max)]

在这个事务范围内,可能会有某些通道上的分布式事务,所以要想办法不允许在[XN1 + 1, XN2max]中出现分布式事务。
只要在做完快照后收到所有节点marker消息前,不再给其它节点发送分布式事务消息,那么就可以保证这个节点不会再发起分布式事务。但是无法阻挡还没有收到marker消息的节点发起分布式事务。
所以,结论是没办法让[XN1 + 1, XN2max]区间不出现分布式事务,这个方法失败了。

3节点的snapshot示例 - 失败

分布式快照的一个简单实现是,在发起快照命令时,选取一个节点作为协调节点,协调节点向所有节点发出checkpoint命令。所有节点开始checkpoint后,不允许执行新的分布式事务,并等待当前节点上执行的分布式事务结束。之后向协调节点回复。协调节点收到所有的回复消息后,通知其它节点开始快照动作。

参考

《Distributed Snapshots: Determining Global States of Distributed Systems》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值