Paxos算法研究

来源:互联网 发布:逍遥模拟器修改mac 编辑:程序博客网 时间:2024/05/22 08:23

 

分布式一致性问题

分布式一致性问题大体可以分为数据一致性和事务一致性,说白了,数据一致性就是多个进程如何对数据的修改达成一致,事务的一致性就是如何将对多个进程的执行处理视为原子性的操作,统一提交或回滚,为了解决以上几个问题,业界提出了很多经典的算法,如二阶段提交,三阶段提交,Paxos等,本篇wiki将对比这三种算法并着重讲解paxos,引出zookeeper的相关算法基础。

二阶段提交

目前的大部分关系型数据库采用此协议实现分布式事务,在此协议中,角色包括协调者和参与者,协议主要包括二个阶段,事务请求阶段,事务提交阶段

事务请求阶段

1)协调者向所有参与者发起事务请求并等待响应

2)所有参与者执行事务操作并响应执行结果,成功执行事务,则响应成功,反之响应失败

事务提交阶段

1)如果所有参与者都响应成功,则协调者向所有参与者发起事务提交

2)参与者执行事务提交并响应提交结果

异常回滚

由协调者向所有参与者发起事务回滚,主要有以下场景:

1)事务请求阶段等待响应超时或有参与者响应失败

优缺点

优点:简单

缺点:单点问题,存在数据不一致,同步阻塞等,归结起来就是没有有效的容错机制,比如协调者挂了就不可用了,或者事务提交阶段,网络异常,有的参与者没收到事务提交请求有的收到了,便出现了数据不一致等。

三阶段提交

三阶段提交其实是对二阶段的改良,主要是把二阶段中的事务请求阶段拆分成了事务询问与事务执行阶段

事务询问阶段

1)协调者向所有参与者询问事务能否执行

2)参与者响应事务可否执行结果,可以返回yes,反之返回no

事务执行阶段

1)如果参与者返回的全是yes,则向所有参与者发起事务执行请求

2)参与者执行事务并返回执行结果

3)等待协调者发送事务提交或异常中断请求,如果没有收到协调者指令,则执行事务提交

事务提交阶段

1)如果所有参与者返回的事务执行结果全是yes,则发起事务提交

2)参与者执行事务提交并返回结果

异常回滚

1)事务执行阶段参与者返回No或超时

2)事务提交阶段参与者返回no或超时

优缺点

优点:部分解决了二阶段的单点问题,如协调者故障后依然可以提交事务

缺点:引用新的问题,有可能在事务应该回滚的情况下,调协者故障,这时却依然提交了事务

Paxos算法

此算法是基于消息传递且有高度容错机制的一致性算法,既然是基于消息传递,那么就会想到拜占庭将军问题(即消息丢失或被篡改),因为现实中系统大多都会部署在一个局域网内,所以假设不存在拜占庭将军问题。算法本身是比较简单的,但算法的描述和推理比较复杂,所以这里分开来讲解。

算法内容

paxos中的角色包括proposer(提案的提出者),acceptor(提案是否通过的表决者),learner(提案获取者),不同的角色不一定是不同的进程,也可能一个进程拥有多个角色

消息以提案表示:<编号,value>,编号为全局递增唯一

算法也包括三个阶段,询问阶段,表决阶段,学习阶段:

询问阶段

1)proposer获取一个提案编号M,根据M向一个acceptor集合(超过半数)的所有acceptor询问当前是否有已经被批准的提案

2)acceptor判断M是否大于自己已经批准过的所有的提案编号,如果是,则返回已批准的编号<M且最大的提案,如果否,可以不响应,如果acceptor之前没有批准过任何提案,则返回空

3)acceptor不再批准编号小于M的提案

4)proposer收到acceptor的响应(acceptor超过半数),如果为空,则自己可以任意设置value的值,如果返回了已批准的提案,则必须以此编号最大的提案的value作为自己的value,生成<M,value>作为自己要发起的提案,如果未超过半数,则重复此阶段

表决阶段

1)proposer确定了自己的提案<M,value>后,会向一个acceptor集合(超过半数且不一定是上一个集合)的所有acceptor发起提案

2)只要acceptor没有批准过比M编号更小的提案,就可以批准该提案

3)超过半数的acceptor批准了提案后,就对value的值达到了一致性,没有的话,则从询问阶段重复

整个过程中:

1)proposer可以提出多个提案

2)acceptor可以批准多个提案

只要各角色严格重复上面的过程,就可以达到最终一致性,但这里在实现时有一种极端场景,如下:

比如proposer1,proposer2交替的向acceptor1,acceptor2,acceptor3发起请求,proposer1向acceptor以m0为编号询问,完成之后proposer2又以m1为编号询问,完成之后acceptor不再批准比m1编号小的提案了,这是proposer1的提案被否决了,这时proposer1又以m2以编号询问,完成后acceptor又不再批准m1了,一直这样下去,就进入死循环了,所以在实现过程中,会选择主proposer,只有主proposer才可以发生提案。

学习阶段

提案被确定后就可以通过learner获取了,获取的方式有很多种,可以根据具体情况选择,如:

1)acceptor批准提案后,立即发送给所有learner

2)acceptor批准后都把提案发给特定的learner,然后由此learner通知其它learner

3)acceptor批准后都把提案发给特定的learner集合,由此集合通知其它learner

算法推理

下面通过数学模型与条件的加强来推导上面算法的内容结论

1)不考虑拜占庭将军问题,如果情况极端一点,只有一个提案被提出,毫无疑问,应该被批准通过,由此得到以下约束:

约束1:acceptor必须批准它收到的第一个提案

这里考虑以下问题:

这种情况下,满足了约束1,但最终无法选定到底是哪个提案,所以这时需要对约束1做一些加强:

约束2:一个提案的选定,需要半数以上的acceptor批准

约束2隐含了一个内容,既然可以有多个proposer提出提案,选定必须是超过半数的acceptor批准才可以,就表示一个acceptor可以批准多了提案,在paxos中,提案由全局唯一编号m和value表示<m,value>,paxos算法其实就是选value的过程,对value的值达成最终一致性

所以,只有当value确定了,整个过程才算结果,那么acceptor可以批准多个提案,在批准了多个不同的提案后,还能最终确定出value,这说明,被批准的多个提案,value是相同的,所以这里得到了约束3:

约束3:如果<m0,value0>提案被选定,那么所有比m0编号高的且被批准的提案,value必须是value0

现在假设这样一种场景:

1)proposer1向acceptor1,2,3提出了一个提案<m0,value0>且被批准了,这时其实就已经被选定了

2)proposer2向acceptor4提出了一个提案<m1,value1>,m1>m0,根据约束1,acceptor4就得批准,这样就与约束3矛盾了,所以这里需要再强化条件约束:

约束4:如果一个提案<m0,value0>被选定后,任何proposer提出的编号更高的提案,value必须是value0

现在,需要证明约束4:

1)假设m0到mn-1的提案value都是value0,证明mn的提案<mn,valuen>value也是value0,即valuen=value0

2)因为m0被选定了,所以表示超过半数的acceptor都批准了m0,那么根据约束3,m0到mn-1的所有被批准的提案value也是value0

3)如果这时mn提案也可以被批准,则意味着如下2种场景:

a)超过半数的acceptor没批准过比mn小的提案

b)超过半数的acceptor批准的比mn小的提案中,编号最大的那个提案value是valuen即valuen=value0,因为<m0,value0>已经被选定了,所以后面被批准的提案的value肯定是value0,这时如果mn提案可以被批准,valuen=value0才可能被批准

综上,推导出了算法的结论

 

 

 

原创粉丝点击