以前的博客《RAFT中成员变更过程以及失败回滚分析 》,分析了副本变更的背景知识和RAFT提出的joint consensus的实现方式。可惜的是,RAFT在其论文和博士论文中都没有给出joint consensus的严格证明,我们在实现oceanbase的乱序日志方案时。初期參照RAFT的joint consensus,但总能找到协议漏洞,于是採用 case by case的方式逐步改动协议,直到我们几个人再 也找不到漏洞的时候,还是不能证明方案设计的正确性。
忘了哪位Google的大神说过“世界上仅仅存在一种一致性协议,那就是PAXOS”。好吧,为了正确性,还是要从伟大的PAXOS出发。
于是,和同事讨论后,提出一种能够证明正确性的成员变更实现方案。
在没有成员变更的情况下,PAXOS决议的的类型仅仅有一种,即某条日志的内容是什么(简称为L<Lid,session>)。引入成员变更后,事实上PAXOS决议的类型多了一种,我们之前一直没有引起重视,即某条日志的PAXOS group是哪些server(简称为G<Gid,Lid, group >)。显然,在提出(而不是批准)一个L的前。就须要确定L的G信息。这是保证正确性的必要条件。
如果我们如果外部有一个全然可靠的地方。可以提供可靠的读写服务,保证多次反复读。都能读到一个一致的信息,我们可以把G存储于此,每次在对L进行PAXOS propose的时候,去读取G信息,决定其所属的group。
不幸的是,不存在这种理想存储情况,我们必须利用现有的集群,把G信息存储多份。这又是一个PAXOS过程。
我们能够构造这样一个系统。满足下面约束:
1. 系统中仅仅有一个leader,在上一条日志没有形成多数派之前,leader不会提出(propose)第二条日志。那么系统中不管发生了什么情况,最多仅仅能有一个未决日志;
2. 系统在写第一条日志前。先写入一个初始配置信息S,指明第一条日志的PAXOS group 信息。
3. 每条日志除了包括原有日志内容外,还须要指明下一条日志的group信息(不过下一条,而不是下一条到无穷大条)。即第i条日志形成多数派后,第i+1条日志的PAXOSgroup 信息就不会变了。此时才干够进入第i + 1条日志的propose阶段。
显然,上述系统是正确的。
这个显然,事实上还是须要进一步证明。。。
在如果上述是正确的前提下,如果想实现成员变更。能够在第x条日志中,写入第x+1条的PAXOS group 信息。须要注意的是,此时x+1这条日志的内容是在new group的,而x+1的PAXOS group 信息是在old group上的,但不管是什么信息,都是满足一致性约束的。
这个系统并发度实在太低了,我们须要给他加速:
1. 系统初始配置信息S。指明了第1条到 第1K条日志的PAXOSgroup 信息;
2. 第1条日志的内容中,记录了第1001条日志的PAXOSgroup 信息,第2条日志的内容中,记录了第1002条日志的PAXOS group信息。也就是说第i 条日志中记录第i + 1K条日志的PAXOS group 信息。
在加速系统中,第1条日志之和第1K + 1条日志有先后关系,而第1条到1K条之间是独立的。是能够多条日志并发进行PAXOS 投票的。这也和我们之前的滑动窗体契合。
在加速系统中,如果须要做成员变更,如果当前滑动窗体的最右边的日志ID是right,则生成一条成员变更信息,信息内容是:从2K + right開始,日志须要写到新的group上,然后将这个信息写入第right + 1条日志中同步给多数派。第2K + right条日志的PAXOS group 信息是记录在1K + right日志内容中,因此。在1K + right日志生成(propose)前。第right + 1条日志必须形成多数派,这是一个约束。
这不同于raft ,必须经历一个joint consensus阶段,仅仅须要一个阶段,即能够完毕成员变更。
详细到实现中,可能还有各种各样的问题,须要进一步细化设计。
版权声明:本文博主原创文章。博客,未经同意不得转载。