Paxos算法深入分析Word格式.docx
《Paxos算法深入分析Word格式.docx》由会员分享,可在线阅读,更多相关《Paxos算法深入分析Word格式.docx(12页珍藏版)》请在冰豆网上搜索。
![Paxos算法深入分析Word格式.docx](https://file1.bdocx.com/fileroot1/2023-1/31/89b70e0f-4a43-4755-a2f6-fdcaccbec7cd/89b70e0f-4a43-4755-a2f6-fdcaccbec7cd1.gif)
任意一个算法运行的实体(例如ATM系统中的S)不会出现拜占庭将军问题(Byzantinefailure)[5],可以简单地理解为结点群在决定命令序列的过程中没有结点受病毒、黑客影响。
二算法介绍与分析
2.1算法详细描述
2.1.1角色分类
便于理解,在这里把一个结点的所有行为概括成3种角色:
Proposer,Acceptor,Learner。
可以认为在一个结点中Paxos算法的行为可以被独立地分成3种对象来执行,对象之间的交互是统一的。
其中:
Proposer向Acceptor提交提案(proposal),提案中含有决议(value)。
Acceptor审批提案。
Learner执行通过审批的提案中含有的决议。
2.1.2核心思想
一个Paxos算法执行的实例中只确定一个决议。
我们使用数学归纳法的思想来保证如何只确定一个决议被批准:
:
一个决议(value)被“批准”,当且仅当含有该决议的提案(proposal)被大多数(majority)的Acceptors所“接受”
某个决议v被批准后,接下来(a)没有任何提案被接受;
或者(b)只有包含决议v的提案被接受。
提案(proposal):
一个有序对<
编号,决议>
决议(value):
一个整数
提案被接受:
某一个Acceptor向该提案的Proposer发出Accepted信息,并将该提案包含的value加入自己的V_A(list)
决议被批准:
含有该决议的提案被Acceptors集合中的任意一个Majority的所有成员接受
Majority:
,例如S=(A,B,C,D,E),其中(A,B,C),(A,C,D)都是majority,而(A,B)不是;
通过反证法可以证明S的任意两个majority的交都不为空,即不会存在两个提案被两个完全不同的majority各自批准的非法场景。
,假设
,即
。
那么
由于
,必然有
,得
,与假设矛盾,故前提假设不成立。
2.1.3Proposer行为分析
(1.1)向所有的Acceptors发送Prepare(N_A)请求;
(1.2)如果收到Reject(N_H)信息,那么重新发送Prepare(N_H+1);
(2.1)如果收到Acceptors集合的任意一个Majority的Promise(N_A,V_A)回复,那么如果所有的V_A均为空,Proposer自由选取一个V_A’,回发Accept(N_A,V_A’);
否则回发Accept(N_A,V_i);
(2.2)如果收到Nack(N_H),回到(1.1)过程,发送Prepare(N_H+1);
(3.1)如果收到任意一个Majority所有成员的Accepted信息(表明选举完成),向所有Proposers发送自身成为leader的消息;
(3.2)向Learner发送value值。
N_A为该次提案的编号;
N_H为当前提案的最高编号;
V_i为V_A中提案编号最高的value;
2.1.4Acceptor行为描述
(1.1)接收Prepare(N_A),如果N_A>
N_H,那么回复Promise(N_A,V_A),并置N_H=N_A;
否则回复Reject(N_H)
(2.1)接收Accept(N_A,V_A),如果N_A<
N_H,那么回复Nack(N_H)信息(暗示了该Proposer提完案后至少有一个其余的Proposer广播了具有更高编号的提案);
否则设置this.V_A=V_A,并且回复Accepted信息。
Promise(N_A,V_A):
向Proposer保证不再接受编号不大于N_H的提案;
Accepted向Proposer发送决议被通过信息;
V_A为Acceptor之前审批过的决议(允许为空);
N_H为Acceptor之前接收提案的最高编号。
2.1.5Learner行为描述
相对来说,Learner的行为理解更简单一些:
学习value,开始执行任务。
2.1.6整体描述
算法在执行过程中,实例和实例之间是异步的;
角色和角色之间既有同步的行为(因为一个完全异步的系统中,一致性问题将是无法被解决的[6]),又有异步的行为。
下表2.1中按照我的理解以全局的角度来说明这其中的关系:
表2.1一次Paxos实例
角色/时段
Phase1
Phase2
Phase3
Proposer(P)
[1]竞争Leader:
向A发送prepare
[1]接收A的promise
[2]选取一个value并发送accept
(*)
Acceptor(A)
[1]接收处理P的prepare
[2]回复reject或promise
[1]接收处理accept
[2]回复accepted或nack
[3]通知L
Learner(L)
无
[1]接收广播学习value或
[2]创建Proposer对象学习value
2.1.7算法总结
该算法巧妙之处在于利用了Majority机制保证了2F+1的容错能力,即具备2F+1个结点的系统最多允许F个结点同时出现故障,并且通过数学归纳的思想步步保障Majority机制。
并且从概率上展示了出现错误(无限循环竞争)的极小可能性。
2.2算法伪代码描述
这个代码换了一种角度来理解本算法,更详细的代码请见[3]。
PaxosPhase1
//proposer状态
anode(maybemorethanone...)decidestobeleader(neednotbeincurrentview):
//静态实现proposal编号唯一性
my_n=max(n_h,my_n)+1,appendnodeID
done=fals
//向所有acceptor发送提案proposal
sendsprepare(vid_h+1,my_n)toallnodesin{views[vid_h],initialcontactnode,itself}
//切换到acceptor状态
ifnodereceivesprepare(vid,n):
//如果收到的是以前的实例(譬如说一个结点刚从故障中恢复,它从日志中获得它出现故障前最近的那个任务,但它并不知道该任务已经由集群中的其他结点集完成)
ifvid<
=vid_h:
returnoldview(vid,views[vid])
//如果是新的任务
elseifn>
n_h:
n_h=n
done=false
//n_a过去接受的proposer的编号,如果以前都没有接受过,那么n_a=v_a=0
returnprepareres(n_a,v_a)
else:
//拒绝
returnreject()
PaxosPhase2
//proposer角色
//获得信息:
该任务已经过时
ifleadergetsoldview(vid,v):
views[vid]=v
vid_h=vid
//转如下一个paxos实例
viewchange
restartpaxos
elseifleadergetsreject():
//被拒绝,延迟,重复本实例,暗示着leader还没确定
delayandrestartpaxos
//从大多数的Acceptor获得回应
elseifleadergetsprepareresfrommajorityofnodesinviews[vid_h]:
//判断是否已经有value被确定,相当重要
ifanyprepareres(n_i,v_i)existssuchthatv_iisnotempty:
//确定value的过程
v=non-emptyvaluev_icorrespondingtohighestn_ireceived
elseleadergetstochooseavalue:
v=setofpingablenodes(includingself)
//回复Accept!
信息
sendaccept(vid_h+1,my_n,v)toallresponders
else:
//准备再次竞争
delayandrestartpaxos
//描述acceptor状态
ifnodegetsaccept(vid,n,v):
//如果是旧的任务
returnoldview(vid,views[vid])
elseifn>
=n_h:
//新的任务,保存该任务,回复accepted!
信息,表明一次选举成功
n_a=n
v_a=v
returnacceptres()
else
//选举中间出了问题,说明有编号更大的提案被接受,所以该提案的proposer的accept!
信息应该被否决
PaxosPhase3
//proposer中的leader角色,获得旧的任务信息
restartpaxos
//获得最终确认信息,即proposer获知选举结束
elseifleadergetsacceptresfromamajorityofnodesinviews[vid_h]:
//开始广播
senddecide(vid_h+1,v_a)toall(includingself)
//learner角色
ifnodegetsdecide(vid,v):
//开始学习
done=true
primaryislowest-numberednodeinv
2.3算法运行实例
这里例举了4个实例。
第一个为结点全部正常的实例;
第二个为一个Acceptor出现故障的实例;
第三个为一个Proposer成为Leader后发生故障的实例;
第四个为两个Proposer进入无限循环竞争的实例。
2.3.1结点全部正常
该实例简单地说明了算法在实际运行中的一般情况:
ClientProposerAcceptorLearner
|||||||
X-------->
||||||Request
|X--------->
|->
|||Prepare(N)
||<
---------X--X--X||Promise(N,{})
|||Accept!
(N,Vn)
---------X--X--X------>
|Accepted(N,Vn)
|<
---------------------------------X--XResponse
2.3.2一个Acceptor出现故障
该实例简单地说明了在算法运行过程中一个Acceptor出现故障的实例。
值得注意的,由于一共有2F+1=3(F=1)个Acceptor,所以仅有一个Acceptor出现故障是在故障容忍范围之内的,不会影响算法的完成:
||||!
||!
!
FAIL!
---------X--X||Promise(N,{})
---------X--X--------->
||||||
2.3.3一个Proposer成为Leader后发生故障
该实例简单地说明了在算法运行过程中一个Proposer成为Leader后发生故障的实例。
由于是Leader出现故障,那么要比一个Acceptor出现故障要复杂得多(但不会影响算法的完成),投票表决过程会被重复,从下图也可以看出:
ClientLeaderAcceptorLearner
X----->
|X------------>
------------X--X--X||Promise(N,{})
|||||||!
Leaderfails!
|||||Accept!
|!
|||||
NEWLEADER!
|||Prepare(N+1)
---------X--X--X||Promise(N+1,{Vn})
(N+1,Vn)
|Accepted(N+1,Vn)
2.3.4两个Proposer进入无限循环竞争
该实例简单地说明了在算法运行过程中一个Proposer发生故障后两个Proposer进入无限循环竞争的实例。
由于该实例由于出现了最坏的情况,算法将永远都不可能完成。
不过该实例的出现的可能性非常小,因为该实例出现无限循环竞争的条件是:
至少存在两个Proposer的Accept!
信息和Prepare信息恰好是按照某种固定顺序相继发送,并且这种顺序永远不能被打乱。
从概率上讲,这在异步通信的环境中是不可能的。
另外,在后面的优化中已经比较详细的介绍了降低出现无限循环竞争情况可能性的优化手段,见3..3。
|||||!
LEADERFAILS
NEWLEADER(knowsN)
---------X--X--X||Promise(N+1,{})
||||||||!
OLDLEADERrecovers
OLDLEADERtriesN+1,denied
------------X--X--X||Nack(N+1)
OLDLEADERtriesN+2
|||Prepare(N+2)
------------X--X--X||Promise(N+2,{})
NEWLEADERproposes,denied
||X--------->
|||<
---------X--X--X||Nack(N+2)
NEWLEADERtriesN+3
|||Prepare(N+3)
---------X--X--X||Promise(N+3,{})
OLDLEADERproposes,denied
(N+2,Vn)
------------X--X--X||Nack(N+3)
||||||||...andsoon...
三算法的思考及优化
3.1体系结构优化
由于分布式系统的体系结构设计引入了一致性问题,并且需要Paxos算法去解决,那么通过对Paxos算法代价的计算可以反过来思考对体系结构的优化。
假设现有函数f(X)用来评价体系结构X的可靠性,函数g(X)来评价体系结构X所带来一致性问题,即X上运行Paxos算法所需要的代价,那么可以定义“增加一台客户端所增加可靠性”函数
其中n为X中结点数量(对应于ATM系统中S的数量)。
同样也可以定义“增加一台客户端所增加一致性问题”函数
那么对
与
进行比较分析后可以设计出最适合应用场景的体系结构。
这只是个人非常粗浅的想法(见笑)。
3.2Reconfiguration优化
在介绍Paxos算法中提到简单的Paxos算法的容错能力是2F+1。
即在总共有2F+1个服务端的情况,只要不超过F个服务端同时出现损毁,采用Paxos算法的分布式系统都能正常运行。
这种2F+1特性是由算法的核心思路Majority投票机制所决定的,我们目前还没有想到提升允许同时损毁的服务端个数,但是可以通过引入合适的Reconfiguration[5]技术降低整个系统处于无法运行的概率。
因为通过Reconfiguration可以减少F个服务端同时损毁的概率。
而事实上Paxos算法的几个改进版本已经采用了这个方法,例如CheapMulti-Paxos[1]。
3.3算法细节优化
可以对算法中提到的Acceptor,Proposer,Learner三个角色的行为进行优化:
1.Proposer:
在一个Proposer在被告之它的proposal编号不是当前最大的时候,它的行为是立即创建另一个具有更大编号的proposal,并发给所有的Acceptors。
这里可以引入一个随机等待机制,即在一个Proposer的proposal被否决后,它随机等待一定时间然后再创建一个具更大编号的proposal进行竞争。
经过实验证明[5],引入随机等待机制以一定概率降低了出现循环竞争的可能性。
我觉得预先设置一组具有一定规律的数字为等待时间,譬如T={2n,2n+1,2n+2…}会比随机效果更好(这个问题下次再给结论了)。
2.Acceptor:
在一个Acceptor收到更大编号的proposal时,可以向它已经promise过的Proposer提早发出Nack信息,这样会降低通信负载。
因为如果对方在发出Accept信息之前收到Nack信息,那么可以减少一次一定会被拒绝的Accept信息的发送;
即便对方已经发送了Accept信息,那么也不会增加任何不必要的通信,因为改Nack信息可以被认为是回复Accept的信息(异步的)。
3.Learner:
在一个proposal被通过后,Learner可以通过创建Proposer角色并向Acceptors发送proposal信息来获得当前最