分布式 一致性Paxos算法(转载)
比较通俗易懂,可以入门,转载地址是http://www.cnblogs.com/linbingdong/p/6253479.html
Paxos算法在分布式领域具有非常重要的地位。但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难。
网上有很多讲解Paxos算法的文章,但是质量参差不齐。看了很多关于Paxos的资料后发现,学习Paxos最好的资料是论文《Paxos Made Simple》,其次是中、英文版维基百科对Paxos的介绍。本文试图带大家一步步揭开Paxos神秘的面纱。
Paxos是什么
Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。
Google Chubby的作者Mike Burrows说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。
虽然Mike Burrows说得有点夸张,但是至少说明了Paxos算法的地位。然而,Paxos算法也因为晦涩难懂而臭名昭著。本文的目的就是带领大家深入浅出理解Paxos算法,不仅理解它的执行流程,还要理解算法的推导过程,作者是怎么一步步想到最终的方案的。只有理解了推导过程,才能深刻掌握该算法的精髓。而且理解推导过程对于我们的思维也是非常有帮助的,可能会给我们带来一些解决问题的思路,对我们有所启发。
问题产生的背景
在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。
注:这里某个数据的值并不只是狭义上的某个数,它可以是一条日志,也可以是一条命令(command)。。。根据应用场景不同,某个数据的值有不同的含义。
相关概念
在Paxos算法中,有三种角色:
- Proposer
- Acceptor
- Learners
在具体的实现中,一个进程可能同时充当多种角色。比如一个进程可能既是Proposer又是Acceptor又是Learner。
还有一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里。
注:
- 暂且认为『提案=value』,即提案只包含value。在我们接下来的推导过程中会发现如果提案只包含value,会有问题,于是我们再对提案重新设计。
- 暂且认为『Proposer可以直接提出提案』。在我们接下来的推导过程中会发现如果Proposer直接提出提案会有问题,需要增加一个学习提案的过程。
Proposer可以提出(propose)提案;Acceptor可以接受(accept)提案;如果某个提案被选定(chosen),那么该提案里的value就被选定了。
回到刚刚说的『对某个数据的值达成一致』,指的是Proposer、Acceptor、Learner都认为同一个value被选定(chosen)。那么,Proposer、Acceptor、Learner分别在什么情况下才能认为某个value被选定呢?
- Proposer:只要Proposer发的提案被Acceptor接受(刚开始先认为只需要一个Acceptor接受即可,在推导过程中会发现需要半数以上的Acceptor同意才行),Proposer就认为该提案里的value被选定了。
- Acceptor:只要Acceptor接受了某个提案,Acceptor就任务该提案里的value被选定了。
- Learner:Acceptor告诉Learner哪个value被选定,Learner就认为那个value被选定。
问题描述
假设有一组可以提出(propose)value(value在提案Proposal里)的进程集合。一个一致性算法需要保证提出的这么多value中,只有一个value被选定(chosen)。如果没有value被提出,就不应该有value被选定。如果一个value被选定,那么所有进程都应该能学习(learn)到这个被选定的value。对于一致性算法,安全性(safaty)要求如下:
- 只有被提出的value才能被选定。
- 只有一个value被选定,并且
- 如果某个进程认为某个value被选定了,那么这个value必须是真的被选定的那个。
我们不去精确地定义其活性(liveness)要求。我们的目标是保证最终有一个提出的value被选定。当一个value被选定后,进程最终也能学习到这个value。
Paxos的目标:保证最终有一个value会被选定,当value被选定后,进程最终也能获取到被选定的value。
假设不同角色之间可以通过发送消息来进行通信,那么:
- 每个角色以任意的速度执行,可能因出错而停止,也可能会重启。一个value被选定后,所有的角色可能失败然后重启,除非那些失败后重启的角色能记录某些信息,否则等他们重启后无法确定被选定的值。
- 消息在传递过程中可能出现任意时长的延迟,可能会重复,也可能丢失。但是消息不会被损坏,即消息内容不会被篡改(拜占庭将军问题)。
推导过程
最简单的方案——只有一个Acceptor
假设只有一个Acceptor(可以有多个Proposer),只要Acceptor接受它收到的第一个提案,则该提案被选定,该提案里的value就是被选定的value。这样就保证只有一个value会被选定。
但是,如果这个唯一的Acceptor宕机了,那么整个系统就无法工作了!
因此,必须要有多个Acceptor!
多个Acceptor
多个Acceptor的情况如下图。那么,如何保证在多个Proposer和多个Acceptor的情况下选定一个value呢?
下面开始寻找解决方案。
如果我们希望即使只有一个Proposer提出了一个value,该value也最终被选定。
那么,就得到下面的约束:
P1:一个Acceptor必须接受它收到的第一个提案。
但是,这又会引出另一个问题:如果每个Proposer分别提出不同的value,发给不同的Acceptor。根据P1,Acceptor分别接受自己收到的value,就导致不同的value被选定。出现了不一致。如下图:
刚刚是因为『一个提案只要被一个Acceptor接受,则该提案的value就被选定了』才导致了出现上面不一致的问题。因此,我们需要加一个规定:
规定:一个提案被选定需要被半数以上的Acceptor接受
这个规定又暗示了:『一个Acceptor必须能够接受不止一个提案!』不然可能导致最终没有value被选定。比如上图的情况。v1、v2、v3都没有被选定,因为它们都只被一个Acceptor的接受。
最开始讲的『提案=value』已经不能满足需求了,于是重新设计提案,给每个提案加上一个提案编号,表示提案被提出的顺序。令『提案=提案编号+value』。
虽然允许多个提案被选定,但必须保证所有被选定的提案都具有相同的value值。否则又会出现不一致。
于是有了下面的约束:
P2:如果某个value为v的提案被选定了,那么每个编号更高的被选定提案的value必须也是v。
一个提案只有被Acceptor接受才可能被选定,因此我们可以把P2约束改写成对Acceptor接受的提案的约束P2a。
P2a:如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v。
只要满足了P2a,就能满足P2。
个Acceptor。Proposer2提出[M1,V1]的提案,Acceptor2~5(半数以上)均接受了该提案,于是对于Acceptor2~5和Proposer2来讲,它们都认为V1被选定。Acceptor1刚刚从宕机状态恢复过来(之前Acceptor1没有收到过任何提案),此时Proposer1向Acceptor1发送了[M2,V2]的提案(V2≠V1且M2>M1),对于Acceptor1来讲,这是它收到的第一个提案。根据P1(一个Acceptor必须接受它收到的第一个提案。),Acceptor1必须接受该提案!同时Acceptor1认为V2被选定。这就出现了两个问题:
- Acceptor1认为V2被选定,Acceptor2~5和Proposer2认为V1被选定。出现了不一致。
- V1被选定了,但是编号更高的被Acceptor1接受的提案[M2,V2]的value为V2,且V2≠V1。这就跟P2a(如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v)矛盾了。
所以我们要对P2a约束进行强化!
P2a是对Acceptor接受的提案约束,但其实提案是Proposer提出来的,所有我们可以对Proposer提出的提案进行约束。得到P2b:
P2b:如果某个value为v的提案被选定了,那么之后任何Proposer提出的编号更高的提案的value必须也是v。
由P2b可以推出P2a进而推出P2。
那么,如何确保在某个value为v的提案被选定后,Proposer提出的编号更高的提案的value都是v呢?
只要满足P2c即可:
P2c:对于任意的N和V,如果提案[N, V]被提出,那么存在一个半数以上的Acceptor组成的集合S,满足以下两个条件中的任意一个:
- S中每个Acceptor都没有接受过编号小于N的提案。
- S中Acceptor接受过的最大编号的提案的value为V。
Proposer生成提案
为了满足P2b,这里有个比较重要的思想:Proposer生成提案之前,应该先去『学习』已经被选定或者可能被选定的value,然后以该value作为自己提出的提案的value。如果没有value被选定,Proposer才可以自己决定value的值。这样才能达成一致。这个学习的阶段是通过一个『Prepare请求』实现的。
于是我们得到了如下的提案生成算法:
- Proposer选择一个新的提案编号N,然后向某个Acceptor集合(半数以上)发送请求,要求该集合中的每个Acceptor做出如下响应(response)。
(a) 向Proposer承诺保证不再接受任何编号小于N的提案。
(b) 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案。
我们将该请求称为编号为N的Prepare请求。
- 如果Proposer收到了半数以上的Acceptor的响应,那么它就可以生成编号为N,Value为V的提案[N,V]。这里的V是所有的响应中编号最大的提案的Value。如果所有的响应中都没有提案,那
么此时V就可以由Proposer自己选择。
生成提案后,Proposer将该提案发送给半数以上的Acceptor集合,并期望这些Acceptor能接受该提案。我们称该请求为Accept请求。(注意:此时接受Accept请求的Acceptor集合不一定是之前响应Prepare请求的Acceptor集合)
Acceptor接受提案
Acceptor可以忽略任何请求(包括Prepare请求和Accept请求)而不用担心破坏算法的安全性。因此,我们这里要讨论的是什么时候Acceptor可以响应一个请求。
我们对Acceptor接受提案给出如下约束:
P1a:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案。
如果Acceptor收到一个编号为N的Prepare请求,在此之前它已经响应过编号大于N的Prepare请求。根据P1a,该Acceptor不可能接受编号为N的提案。因此,该Acceptor可以忽略编号为N的Prepare请求。当然,也可以回复一个error,让Proposer尽早知道自己的提案不会被接受。
因此,一个Acceptor只需记住:1. 已接受的编号最大的提案 2. 已响应的请求的最大编号。
Paxos算法描述
经过上面的推导,我们总结下Paxos算法的流程。
Paxos算法分为两个阶段。具体如下:
- 阶段一:
(a) Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。
(b) 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
- 阶段二:
(a) 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。
(b) 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。
Learner学习被选定的value
Learner学习(获取)被选定的value有如下三种方案:
如何保证Paxos算法的活性
通过选取主Proposer,就可以保证Paxos算法的活性。至此,我们得到一个既能保证安全性,又能保证活性的分布式一致性算法——Paxos算法。
文章2,来自http://blog.csdn.net/21aspnet/article/details/50700123
年提出的一种基于消息传递且具有高度容错特性的一致性算法。
Paxos算法一开始非常难以理解,但是一旦理解其实也并不难,之所以难理解其实是因为作者讲的故事难理解。
Paxos算法维基百科https://en.wikipedia.org/wiki/Paxos_(computer_science)
篇帖子是讲的非常好的,
分别是:以两军问题为背景来演绎Basic Paxos和Paxos算法细节详解(一)--通过现实世界描述算法
个帖子之后再结合原论文才看懂的。
个角色:Client Proposer Acceptor Learner。
Client:产生议题者
Proposer :提议者
Acceptor:决策者
Learner:最终决策学习者,也就是执行者。
Proposer拿着Client的议题去向Acceptor提议,让Acceptor来决策。
Proposer提出议题,Acceptor初步接受或者Acceptor初步不接受。
Acceptor初步接受则Proposer再次向Acceptor确认是否最终接受。
Acceptor最终接受或者Acceptor最终不接受。
Learner最终学习的目标是向所有Acceptor学习,如果有多数派个Acceptor最终接受了某提议,那就得到了最终的结果,算法的目的就达到了。
最基本的Message flow: Basic Paxos演示图如下图所示,其他情况可以参考百科。
图解:
A1,,A2和A3就是Acceptor。
P1,p2和p3就是Proposer。浅色的P1和P2说明是进行提议,深色的P1和P2说明是拿到表决。
表明是每次提议序号,递增即可。黑色的图表示被黑了,也就是否决。方块表示投票结果,绿方块表示投票通过,红色菱形表示最终的投票结果。
整个事件是按照时间线从左到右发展。
事件发展:
第一个框代表第一阶段--提议
,A2记录下,因为之前没有其他的序号所以成功了,然后返回标志给p2;
,A1记录下,因为之前没有其他的序号所以成功了,然后返回标志给p1;
,A3记录下,因为之前没有其他的序号所以成功了,然后返回标志给p1;
问题来了
,A2已经记录下提议序号2,2>1,所以不成功;
,A1已经记录下提议序号1,1>2,所以成功;,然后返回标志给p2;
,A3已经记录下提议序号1,1>2,所以成功;,然后返回标志给p2;
第二个框代表第二阶段--确认提议(投票)
,A1已经记录下提议序号2,1<2,所以不确认,然后p1继续提议序号是3,周而复始...;
,A2已经记录下提议序号2,2=2,所以确认成功;,然后返回投票标志给p2;
,A3已经记录下提议序号2,2=2,所以确认成功;,然后返回投票标志给p2;
,A1已经记录下提议序号3,2<3,所以不确认,;然后p2继续提议序号是4,周而复始...;
问题来了
,A1已经记录下确认序号2,1<2,所以不确认,然后返回确认序号2;
,A3已经记录下确认序号2,1<2,所以不确认,然后返回确认序号2;
。
。
Paxos过程结束了,这样,一致性得到了保证,算法运行到最后所有的proposer都投"2"所有的acceptor都接受这个议题,也就是说在最初的第二阶段,议题是先入为主的,谁先占了先机,后面的proposer在第一阶段就会学习到这个议题而修改自己本身的议题,才能让一致性得到保证,这就是paxos算法的一个过程。该算法就是为了追求结果的一致性。
文章3,来自:http://www.cnblogs.com/cchust/p/5617989.html
Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法。Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。在工程实践意义上来说,就是可以通过Paxos实现多副本一致性,分布式锁,名字管理,序列号分配等。比如,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个"一致性算法"以保证每个节点看到的指令一致。本文首先会讲原始的Paxos算法(Basic Paxos),主要描述二阶段提交过程,然后会着重讲Paxos算法的变种(Multi Paxos),它是对Basic Paxos的优化,而且更适合工程实践,最后我会通过Q&A的方式,给出我在学习Paxos算法中的疑问,以及我对这些疑问的理解。
概念与术语
Proposer:提议发起者,处理客户端请求,将客户端的请求发送到集群中,以便决定这个值是否可以被批准。
Acceptor:提议批准者,负责处理接收到的提议,他们的回复就是一次投票,会存储一些状态来决定是否接收一个值。
replica:节点或者副本,分布式系统中的一个server,一般是一台单独的物理机或者虚拟机,同时承担paxos中的提议者和接收者角色。
ProposalId:每个提议都有一个编号,编号高的提议优先级高。
Paxos Instance:Paxos中用来在多个节点之间对同一个值达成一致的过程,比如同一个日志序列号:logIndex,不同的logIndex属于不同的Paxos Instance。
acceptedProposal:在一个Paxos Instance内,已经接收过的提议
acceptedValue:在一个Paxos Instance内,已经接收过的提议对应的值。
minProposal:在一个Paxos Instance内,当前接收的最小提议值,会不断更新
Basic-Paxos算法
基于Paxos协议构建的系统,只需要系统中超过半数的节点在线且相互通信正常即可正常对外提供服务。它的核心实现Paxos Instance主要包括两个阶段:准备阶段(prepare phase)和提议阶段(accept phase)。如下图所示:
,生成一个更高的提议;
5.到这里表示在当前paxos instance内,没有优先级更高的提议,可以进入第二阶段,广播accept(n,value)到所有节点;
6.接收者比较n和minProposal,如果n>=minProposal,则acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;
否则,返回minProposal
7.提议者接收到过半数请求后,如果发现有返回值>n,表示有更新的提议,跳转1;否则value达成一致。
从上述流程可知,并发情况下,可能会出现第4步或者第7步频繁重试的情况,导致性能低下,更严重者可能导致永远都无法达成一致的情况,就是所谓的"活锁",如下图所示:
1.S1作为提议者,发起prepare(3.1),并在S1,S2和S3达成多数派;
2.随后S5作为提议者
,发起了prepare(3.5),并在S3,S4和S5达成多数派;
3.S1发起accept(3.1,value1),由于S3上提议 3.5>3.1,导致accept请求无法达成多数派,S1尝试重新生成提议
4.S1发起prepare(4.1),并在S1,S2和S3达成多数派
5.S5发起accpet(3.5,value5),由于S3上提议4.1>3.5,导致accept请求无法达成多数派,S5尝试重新生成提议
6.S5发起prepare(5.5),并在S3,S4和S5达成多数派,导致后续的S1发起的accept(4.1,value1)失败
......
prepare阶段的作用
从Basic-Paxos的描述可知,需要通过两阶段来最终确定一个值,由于轮回多,导致性能低下,至少两次网络RTT。那么prepare阶段能否省去?如下图所示:
1.S1首先发起accept(1,red),并在S1,S2和S3达成多数派,red在S1,S2,S3上持久化
2.随后S5发起accept(5,blue),对于S3而言,由于接收到更新的提议,会将acceptedValue值改为blue
3.那么S3,S4和S5达成多数派,blue在S3,S4和S5持久化
4.最后的结果是,S1和S2的值是red,而S3,S4和S5的值是blue,没有达成一致。
所以两阶段必不可少,Prepare阶段的作用是阻塞旧的提议,并且返回已经接收到的acceptedProposal。同时也可以看到的是,假设只有S1提议,则不会出现问题,这就是我们下面要讲的Multi-Paxos。
Multi-paxos算法
Paxos是对一个值达成一致,Multi-Paxos是连续多个paxos instance来对多个值达成一致,这里最核心的原因是multi-paxos协议中有一个Leader。Leader是系统中唯一的Proposal,在lease租约周期内所有提案都有相同的ProposalId,可以跳过prepare阶段,议案只有accept过程,一个ProposalId可以对应多个Value,所以称为Multi-Paxos。
选举
首先我们需要有一个leader,其实选主的实质也是一次Paxos算法的过程,只不过这次Paxos确定的"谁是leader"这个值。由于任何一个节点都可以发起提议,在并发情况下,可能会出现多主的情况,比如A,B先后当选为leader。为了避免频繁选主,当选leader的节点要马上树立自己的leader权威(让其它节点知道它是leader),写一条特殊日志(start-working日志)确认其身份。根据多数派原则,只有一个leader的startworking日志可以达成多数派。leader确认身份后,可以通过了lease机制(租约)维持自己的leader身份,使得其它proposal不再发起提案,这样就进入了leader任期,由于没有并发冲突,因此可以跳过prepare阶段,直接进入accept阶段。通过分析可知,选出leader后,leader任期内的所有日志都只需要一个网络RTT(Round Trip Time)即可达成一致。
新主恢复流程
由于Paxos中并没有限制,任何节点都可以参与选主并最终成为leader,这就无法保证新选出的leader包含了所有日志,可能存在空洞,因此在真正提供服务前,还存在一个获取所有已提交日志的恢复过程。新主向所有成员查询最大logId的请求,收到多数派响应后,选择最大的logId作为日志恢复结束点,这里多数派的意义在于恢复结束点包含了所有达成一致的日志,当然也可能包含了没有达成多数派的日志。拿到logId后,从头开始对每个logId逐条进行paxos协议,因为在新主获得所有日志之前,系统是无法提供服务的。为了优化,引入了confirm机制,就是将已经达成一致的logId告诉其它acceptor,acceptor写一条confirm日志到日志文件中。那么新主在重启后,扫描本地日志,对于已经拥有confirm日志的log,就不会重新发起paxos了。同样的,在响应客户端请求时,对于没有confirm日志的log,需要重新发起一轮paxos。由于没有严格要求confirm日志的位置,可以批量发送。为了确保重启时,不需要对太多已提价的log进行paxos,需要将confirm日志与最新提交的logId保持一定的距离。
次磁盘写操作(prepare,promise)和2次网络RTT(prepare,promise)。Multi-Paxos利用一阶段提交(省去Prepare阶段),将一次日志确认缩短为一个RTT和一次磁盘写;通过confirm机制,可以缩短新主的恢复时间。为了提高性能,我们还可以实现一批日志作为一个组提交,要么成功一批,要么都不成功,这点类似于group-commit,通过RT换取吞吐量。
个节点,两个IDC,发生分区后会发现任何一个IDC都无法达成多数派,导致无法选出主的问题。因此一般Paxos节点数都是奇数个,而且在部署节点时,IDC节点的分布也要考虑。
(3).磁盘故障
前面两种异常,磁盘都是OK的,即已接收到的日志以及对应confirm日志都在。如果磁盘故障了,节点再加入就类似于一个新节点,上面没有任何日志和Proposal信息。这种情况会导致一个问题就是,这个节点可能会promise一个比已经promise过的最大proposalID更小的proposal,这就违背了Paxos原则。因此重启后,节点不能参与Paxos Instance,它需要先追上Leader,当观察到一次完整的paxos instance时该节点结束不能promise/ack状态。
2.Follower异常(宕机,磁盘损坏等)
对于Follower异常,则处理要简单的多,因为follower本身不对外提供服务(日志可能不全),对于leader而言,只要能达成多数派,就可以对外提供服务。follower重启后,没有promise能力,直到追上leader为止。
主N备的同步方式有啥区别?主1备2个副本,主库crash后,通过HA工具来进行切换,提升备库为主库。在强一致场景下,复制可以开启强同步,Oracle和Mysql都是类似的复制模式。但是如果备库网络抖动,或者crash,都会导致日志同步失败,服务不可用。为此,可以引入1主N备的多副本形式,我们对比都是3副本的情况,一个是基于传统的1主2备,另一种基于paxos的1主2备。传统的1主两备,进行日志同步时,只要有一个副本接收到日志并就持久化成功,就可以返回,在一定程度上解决了网络抖动和备库crash问题。但如果主库出问题后,还是要借助于HA工具来进行切换,那么HA切换工具的可用性如何来保证又成为一个问题。基于Paxos的多副本同步其实是在1主N备的基础上引入了一致性协议,这样整个系统的可用性完全有3个副本控制,不需要额外的HA工具。而实际上,很多系统为了保证多节点HA工具获取主备信息的一致性,采用了zookeeper等第三方接口来实现分布式锁,其实本质也是基于Paxos来实现的。
步来看,可以一定程度上保证主备一致性,但是进行rollback和replay时,实际上是往new-Slave上写数据,这一定程度上造成了双写,如果此时new—Master也在写同一条记录,可能会导致写覆盖等问题。
(8).如果开启半同步呢?old-Master crash时,仍然可能比old-Slave多一个group的binlog,所以仍然需要借助于rollback和replay,依然避免不了双写,所以也不能做到严格意义上的强一致。
2.分布式事务与Paxos协议的关系?
在数据库领域,提到分布式系统,就会提到分布式事务。Paxos协议与分布式事务并不是同一层面的东西。分布式事务的作用是保证跨节点事务的原子性,涉及事务的节点要么都提交(执行成功),要么都不提交(回滚)。分布式事务的一致性通常通过2PC来保证(Two-Phase Commit, 2PC),这里面涉及到一个协调者和若干个参与者。第一阶段,协调者询问参与者事务是否可以执行,参与者回复同意(本地执行成功),回复取消(本地执行失败)。第二阶段,协调者根据第一阶段的投票结果进行决策,当且仅当所有的参与者同意提交事务时才能提交,否则回滚。2PC的最大问题是,协调者是单点(需要有一个备用节点),另外协议是阻塞协议,任何一个参与者故障,都需要等待(可以通过加入超时机制)。Paxos协议用于解决多个副本之间的一致性问题。比如日志同步,保证各个节点的日志一致性,或者选主(主故障情况下),保证投票达成一致,选主的唯一性。简而言之,2PC用于保证多个数据分片上事务的原子性,Paxos协议用于保证同一个数据分片在多个副本的一致性,所以两者可以是互补的关系,绝不是替代关系。对于2PC协调者单点问题,可以利用Paxos协议解决,当协调者出问题时,选一个新的协调者继续提供服务。工程实践中,Google Spanner,Google Chubby就是利用Paxos来实现多副本日志同步。
3.如何将Paxos应用于传统的数据库复制协议中?
复制协议相当于是对Paxos的定制应用,通过对一系列日志进行投票确认达成多数派,就相当于日志已经在多数派持久化成功。副本通过应用已经持久化的日志,实现与Master节点同步。由于数据库ACID特性,本质是由一个一致的状态到另外一个一致的状态,每次事务操作都是对应数据库状态的变更,并生成一条日志。由于client操作有先后顺序,因此需要保证日志的先后的顺序,在任何副本中,不仅仅要保证所有日志都持久化了,而且要保证顺序。对于每条日志,通过一个logID标示,logID严格递增(标示顺序),由leader对每个日志进行投票达成多数派,如果中途发生了leader切换,对于新leader中logID的"空洞",需要重新投票,确认日志的有效性。
4.Multi-Paxos的非leader节点可以提供服务吗?
Multi-Paxos协议中只有leader确保包含了所有已经已经持久化的日志,当然本地已经持久化的日志不一定达成了多数派,因此对于没有confirm的日志,需要再进行一次投票,然后将最新的结果返回给client。而非leader节点不一定有所有最新的数据,需要通过leader确认,所以一般工程实现中,所有的读写服务都由leader提供。
5.客户端请求过程中失败了,如何处理?
client向leader发起一次请求,leader在返回前crash了。对于client而言,这次操作可能成功也可能失败。因此client需要检查操作的结果,确定是否要重新操作。如果leader在本地持久化后,并没有达成多数派时就crash,新leader首先会从各个副本获取最大的logID作为恢复结束点,对于它本地没有confirm的日志进行Paxos确认,如果此时达成多数派,则应用成功,如果没有则不应用。client进行检查时,会知道它的操作是否成功。当然具体工程实践中,这里面涉及到client超时时间,以及选主的时间和日志恢复时间。
分布式 一致性Paxos算法(转载)的更多相关文章
- 理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos
理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos Cheap Paxos Message flow: Cheap Multi-Paxos Fast Paxos ...
- 分布式一致性hash算法
写在前面 在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...
- 理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos
理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos Generalized Paxos Byzantine Paxos Byzantine ...
- 理解分布式一致性:Paxos协议之Multi-Paxos
理解分布式一致性:Paxos协议之Multi-Paxos Multi-Paxos without failures Multi-Paxos when phase 1 can be skipped Mu ...
- 理解分布式一致性:Paxos协议之Basic Paxos
理解分布式一致性:Paxos协议之Basic Paxos 角色 Proposal Number & Agreed Value Basic Paxos Basic Paxos without f ...
- chandy-lamport 分布式一致性快照 算法详细介绍
在一个分布式计算系统中,为了保证数据的一致性需要对数据进行一致性快照.Flink和spark在做流失计算的时候都借鉴了chandy-lamport算法的原理,这篇文章就是对chandy-lamport ...
- memcache分布式 [一致性hash算法] 的php实现
最近在看一些分布式方面的文章,所以就用php实现一致性hash来练练手,以前一般用的是最原始的hash取模做分布式,当生产过程中添加或删除一台memcache都会造成数据的全部失效,一致性hash就是 ...
- 分布式一致性协议之:Paxos算法(转)
Paxos算法的难理解与算法的知名度一样令人敬仰,从我个人的经历而言,难理解的原因并不是该算法高深到大家智商不够,而在于Lamport在表达该算法时过于晦涩且缺乏一个完整的应用场景.如果大师能换种思路 ...
- Paxos算法1-算法形成理论[转载]
地址 http://blog.csdn.net/chen77716/article/details/6166675 中文wiki http://zh.wikipedia.org/zh-cn/Paxos ...
随机推荐
- realpython教程之机器学习之Windows下的环境配置
不得不说,realPython的教程确实写的仔细,准确,有逻辑.果然高质量的学习材料还是更利于学的. 反观我们学校,似乎就有些急功近利了.连Python语言基础都没学,就直接讲深度学习.完全不符合学习 ...
- day34 并行并发、进程开启、僵尸及孤儿进程
day34 并行并发.进程开启.僵尸及孤儿进程 1.并行与并发 什么是并行? 并行指的是多个进程同时被执行,是真正意义上的同时 什么是并发? 并发指的是多个程序看上去被同时执行,这是因为cpu在多个程 ...
- vi操作笔记一
vi命令 gg 到首行 shift + 4 跳到该行最后一个字符 shift + 6 跳到该行首个字符 shift + g 到尾行 vi 可视 G 全选 = 程序对齐 gg 到首行 vi 可视 ...
- sql server 中 like 中文不匹配问题解决就这么简单
原文:sql server 中 like 中文不匹配问题解决就这么简单 MS-SQL Server select * from Book where BookName like'%C语言%' 在SQ ...
- django初步了解4
django单表查询 必知必会13条 1.all() 查询所有 QuerySet res=models.Book.objects.all()#惰性查询 print(res) for i in res: ...
- Python特色数据类型--元组
元组是不可改变的,创建后就不能做任何修改操作了 1.元组用()表示
- wc、iconv命令
一.wc:统计文件打印换行符,单词和字节数 语法: wc [OPTION] ... [FILE] ... wc [OPTION] ... --files0-from = F 描 ...
- linux kprobe rootkit学习
介绍 <linux二进制分析>中提到了使用kprobe来写内核rootkit,还给出了一个简单的源码实现,这里看一下他的源码 kprobe kprobe的介绍可以看下面这几篇文章 介绍:h ...
- Jmeter入门(一)干货吐槽
前言:性能测试的基础是功能测试.性能测试的核心是业务场景,而这个业务场景是从功能测试的场景测试中提取出来的. 所以一个软件的测试顺序是:功能(接口)→性能N(接口)→自动化(接口) 接口测试则分布在每 ...
- 解决github pages和github .md文件图片不显示
博客园上传的图片,在github上无法显示. 在github项目下建立img文件夹,放上图片 两种方式 项目绝对路径 https://raw.githubusercontent.com/用户名/项目名 ...