/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/
author: 张俊林
本文节选自《大数据日知录:架构与算法》第二章“数据复制与一致性”
|2.4.4 Paxos协议
在过去十年里,Paxos基本成为了分布式领域内一致性协议的代名词。Google的粗粒度锁服务Chubby的设计开发者Burrows曾经说过:“所有一致性协议本质上要么是Paxos要么是其变体”。Paxos是几乎所有相关课程必讲内容以及很多其它一致性协议的起点,Paxos的提出者LeslieLamport也因其对分布式系统的杰出理论贡献获得了2013年图灵奖。
除了其基础性和重要性之外,Paxos也一直以难以理解闻名。Lamport最初的论文晦涩难懂,很少有人能够透彻理解其精髓,直到之后一系列试图以简明清晰讲解Paxos机制的论文发表后此现象才得以缓解。由此带来的一个副作用是:在根据Paxos原理构造实际可用系统时有一定程度的困难,很多声明基于Paxos原理构造的系统在实现时往往会引入开发者自己的理解,这造成的后果是尽管Paxos在理论上可以证明其正确性,但是实现时经过改造的一致性协议并不能保证这一点。Burrows也曾说过:“Paxos算法描述和真实实现之间存在巨大鸿沟……所以最终系统很可能是基于一个未经证明的一致性协议”。
本节讲述Paxos协议,首先介绍副本状态机模型,之后介绍Paxos的一些基本概念,然后描述Paxos协议本身内容。其实从协议内容本身来看很好理解其运作机制,好像体会不到其难理解性,这里需要强调的是:Paxos的难理解性在于是什么因素导致协议以此种方式呈现以及其正确性证明过程而非最终协议内容本身,鉴于其复杂性和篇幅原因,对其感兴趣的读者可参考文献9、10、11,本节以描述其本身机制为主。
|2.4.4.1副本状态机模型(Replicated State Machines)
在分布式环境下,一致性协议的应用场景一般会采用副本状态机来表达,这是对各种不同应用场景的一种抽象化表述。
一种典型的实现副本状态机的机制是采用Log副本的方式(参考图2-20)。集群中多台服务器各自保存一份Log副本及内部状态机,Log内顺序记载客户端发来的操作指令,服务器依次执行Log内的指令并将其体现到内部状态机上,如果保证每台机器内的Log副本内容完全一致,那么对应的状态机也可以保证整体状态一致。一致性协议的作用就是保证各个Log副本数据的一致性,比如图2-20中的一致性模块(Consensus Module)即起此作用。某台服务器在接收到客户端的操作指令后,将其追加到自身的Log尾部,然后和其它服务器的一致性模块进行通信,保证其它服务器(即使是有服务器发生故障)的Log最终能够以同样的顺序保存同样的操作指令,当操作指令能够正确复制,那么每台服务器按照Log内记录顺序执行操作指令,最终所有服务器的内部状态保持一致,服务器将执行操作命令后的状态结果返回客户端作为操作结果。即通过这种方式使得整个集群对于外部客户端看起来就像单机一样。
在实际实现上述副本状态机中的一致性协议时,往往追求以下几个特性:
1. 安全性(Safety)保证:即非拜占庭模型(此概念参考下节内容)下,状态机从不返回错误的结果,多个提议中只会有一个被选中;
2. 可用性(Available)保证:只要大多数服务器正常,则整个服务保持可用。比如副本状态机有5台服务器,那么最多可以容忍2台服务器发生故障,此时整个服务仍然可用,即对于2f+1台副本状态机的配置,最多可容忍f个状态机失效;
一般情况下,大多数状态机维护Log一致即可快速通知客户端操作成功,这样避免了少数最慢的状态机拖慢整个请求响应速度。
|2.4.4.2 Paxos基本概念
Paxos又可以细分为两种:单Paxos(Single-Decree Paxos)和多Paxos(Multi-Paxos)。对照上节的副本状态机模型,直观上可以如此理解两者的差异:所谓单Paxos,即副本状态机中各个服务器针对Log中固定某个位置的操作命令通过协议达成一致,因为可能某一时刻不同服务器中Log中相同位置的操作命令是不一样的,通过执行协议后使得各个服务器对应某个固定位置的操作命令达成一致。而多Paxos则是指这些服务器对应的Log内容中多个位置的操作命令序列通过协议保持一致。多Paxos往往是同时运行的多个单Paxos协议共同执行的结果,后文讲解Paxos协议主要以单Paxos为主,这点需要读者注意。
在讲解Paxos协议之前,为了方便叙述与理解,首先介绍一些相关基本概念。
首先是并行进程(对应副本状态机上每台服务器的一致性模块)的角色(Role)概念,Paxos协议下不同并行进程可能承担的三种角色如下:
倡议者(Proposer):倡议者可以提出提议(数值或操作命令等)以供投票表决;
接受者(Acceptor):接受者可以对倡议者提出的提议进行投票表决,从众多提议中选出唯一确定的一个;
学习者(Learner):学习者无倡议投票权,但是可以从接受者那里获知是哪个提议最终被选中;
在一致性协议框架中,一个并行进程可以同时承担以上多种角色。
另外一个概念是异步通信环境下的非拜占庭模型(Non-Byzantine Model),其含义是:
1并发进程的行为可以以任意速度执行,允许运行失败,在失败后也许会重启并再次运行;
2.并发进程之间通过异步方式发送信息通信,通信时间可以任意长,信息可能会在传输过程中丢失,也允许重复发送相同的信息,多重信息的顺序可以任意。但是有一点:信息不允许被篡改(在真实分布计算环境下,这一条可以通过内容完整性检测很容易解决)。
Paxos协议以及很多一致性协议都是在非拜占庭模型下的,即在非拜占庭条件下,Paxos协议可以就不同提议达成一致,拜占庭模型下情况会更加复杂一些。
|2.4.4.3 Paxos一致性协议
Paxos的目的是在非拜占庭条件下,当多个并行进程提出不同的操作命令(下文统称为倡议)时,如何能够达成一致。如果归纳Paxos协议,可以将其描述为以下两阶段过程:
- [阶段一]
1.1【倡议者视角】倡议者选择倡议编号n,然后向大多数(即超过半数以上)接受者发送Prepare请求,请求中附带倡议编号n。
1.2【接受者视角】对于某个接受者来说,如果接收到带有倡议编号n的Prepare请求,则做如下判断:若倡议编号n比此接受者之前响应过的任何其它Prepare请求附带的倡议编号都大,那么此接受者会给倡议者以响应,并承诺不会响应之后接收到的其它任何倡议编号小于n的请求,另外,如果接受者曾经响应过2.2阶段的Accept请求,则将所有响应的Accept请求中倡议编号最高的倡议内容发送给倡议者,倡议内容包括两项信息:Accept请求中的倡议编号以及其倡议值。若倡议编号n不比此接受者之前响应过的任何其它Prepare请求附带的倡议编号都大,那么此接受者不会给倡议者以响应。
- [阶段二]
2.1【倡议者视角】如果倡议者接收到大多数接受者关于带有倡议编号n的Prepare请求的响应,那么倡议者向这些接受者发送Accept请求,Accept请求附带两个信息:倡议编号n以及倡议值v。倡议值v的选择方式如下:如果在1.2阶段接受者返回了自己曾经接受的具有最高倡议编号Accept请求倡议内容,则从这些倡议内容里面选择倡议编号最高的并将其倡议值作为倡议值v;如果1.2阶段没有收到任何接受者的Accept请求倡议内容,则可以任意赋值给倡议值v。
2.2【接受者视角】如果接受者接收到了任意倡议编号为n的Accept请求,则接受者接受此请求,除非在此期间接受者响应过具有比n更高编号的Prepare请求。通过以上两阶段过程即可选出唯一的倡议值,对于学习者来说,其需要从接受者那里获知到底是哪个倡议值被选出。一个直观的方法如下:每当接受者执行完2.2步骤,即接受某个Accept请求后,由其通知所有学习者其所接受的倡议,这样,学习者很快习得是哪个倡议被最终选出。但是这种方式会导致大量通信,因为任意一个接受者会通知任意一个学习者,如果有m个接受者,n个学习者,则需要m*n次通信。一个替代策略是:从众多学习者中选择一个作为代表,由其从接受者那里获知最终被选出的倡议,然后再由其通知其它学习者,这样可以将通信量降为m+n。但是这个方案中如果这个学习者代表发生故障,其它学习者无从知晓倡议值。考虑到健壮性和通信量两个因素,可以采取折中方法:选出若干学习者作为代表,由这些代表从接受者那里获知最终倡议值,然后通知其它学习者。
通过以上流程,如果有多个并发进程提出各自的倡议值,Paxos就可以保证从中选出且只选出一个唯一确定的倡议值,以此来达到副本状态机保持状态一致的目标。
上述内容是Paxos一致性协议的理论方案,正向上文所述,在实际实现时还需要考虑很多问题,比如如何保证不同进程所采纳的倡议编号全局唯一且递增增长、异常处理(比如倡议者或者接受者崩溃的处理策略)、状态持久化等等,这些在不同系统实现时都可能采取各异的策略。