分布式一致性算法--Paxos

      Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法。Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。在工程实践意义上来讲,就是能够经过Paxos实现多副本一致性,分布式锁,名字管理,序列号分配等。好比,在一个分布式数据库系统中,若是各节点的初始状态一致,每一个节点执行相同的操做序列,那么他们最后能获得一个一致的状态。为保证每一个节点执行相同的命令序列,须要在每一条指令上执行一个“一致性算法”以保证每一个节点看到的指令一致。本文首先会讲原始的Paxos算法(Basic Paxos),主要描述二阶段提交过程,而后会着重讲Paxos算法的变种(Multi Paxos),它是对Basic Paxos的优化,并且更适合工程实践,最后我会经过Q&A的方式,给出我在学习Paxos算法中的疑问,以及我对这些疑问的理解。html

概念与术语
Proposer:提议发起者,处理客户端请求,将客户端的请求发送到集群中,以便决定这个值是否能够被批准。
Acceptor:提议批准者,负责处理接收到的提议,他们的回复就是一次投票,会存储一些状态来决定是否接收一个值。
replica:节点或者副本,分布式系统中的一个server,通常是一台单独的物理机或者虚拟机,同时承担paxos中的提议者和接收者角色。
ProposalId:每一个提议都有一个编号,编号高的提议优先级高。
Paxos Instance:Paxos中用来在多个节点之间对同一个值达成一致的过程,好比同一个日志序列号:logIndex,不一样的logIndex属于不一样的Paxos Instance。
acceptedProposal:在一个Paxos Instance内,已经接收过的提议
acceptedValue:在一个Paxos Instance内,已经接收过的提议对应的值。
minProposal:在一个Paxos Instance内,当前接收的最小提议值,会不断更新node

Basic-Paxos算法
     基于Paxos协议构建的系统,只须要系统中超过半数的节点在线且相互通讯正常便可正常对外提供服务。它的核心实现Paxos Instance主要包括两个阶段:准备阶段(prepare phase)和提议阶段(accept phase)。以下图所示:算法


1.获取一个ProposalId,为了保证ProposalId递增,能够采用时间戳+serverId方式生成;
2.提议者向全部节点广播prepare(n)请求;
3.接收者比较n和minProposal,若是n>minProposal,表示有更新的提议,minProposal=n;不然将(acceptedProposal,acceptedValue)返回;
4.提议者接收到过半数请求后,若是发现有acceptedValue返回,表示有更新的提议,保存acceptedValue到本地,而后跳转1,生成一个更高的提议;
5.到这里表示在当前paxos instance内,没有优先级更高的提议,能够进入第二阶段,广播accept(n,value)到全部节点;
6.接收者比较n和minProposal,若是n>=minProposal,则acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;
不然,返回minProposal
7.提议者接收到过半数请求后,若是发现有返回值>n,表示有更新的提议,跳转1;不然value达成一致。
从上述流程可知,并发状况下,可能会出现第4步或者第7步频繁重试的状况,致使性能低下,更严重者可能致使永远都没法达成一致的状况,就是所谓的“活锁”,以下图所示:sql

 

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)失败数据库

......promise

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保持必定的距离。

性能优化
      Basic-Paxos一第二天志确认,须要至少2次磁盘写操做(prepare,promise)和2次网络RTT(prepare,promise)。Multi-Paxos利用一阶段提交(省去Prepare阶段),将一第二天志确认缩短为一个RTT和一次磁盘写;经过confirm机制,能够缩短新主的恢复时间。为了提升性能,咱们还能够实现一批日志做为一个组提交,要么成功一批,要么都不成功,这点相似于group-commit,经过RT换取吞吐量。

安全性(异常处理)
1.Leader异常
Leader在任期内,须要按期给各个节点发送心跳,已告知它还活着(正常工做),若是一个节点在超时时间内仍然没有收到心跳,它会尝试发起选主流程。Leader异常了,则全部的节点前后都会出现超时,进入选主流程,选出新的主,而后新主进入恢复流程,最后再对外提供服务。咱们一般所说的异常包括如下三类:
(1).进程crash(OS crash)
Leader进程crash和Os crash相似,只要重启时间大于心跳超时时间都会致使节点认为leader挂了,触发从新选主流程。
(2).节点网络异常(节点所在网络分区)
Leader网络异常一样会致使其它节点收不到心跳,但有可能leader是活着的,只不过发生了网络抖动,所以心跳超时不能设置的过短,不然容易由于网络抖动形成频繁选主。另一种状况是,节点所在的IDC发生了分区,则同一个IDC的节点相互还能够通讯,若是IDC中节点能构成多数派,则正常对外服务,若是不能,好比总共4个节点,两个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为止。

Q&A
1.Paxos协议数据同步方式相对于基于传统1主N备的同步方式有啥区别?
      通常状况下,传统数据库的高可用都是基于主备来实现,1主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来实现的。

      我这里以MySQL的主备复制一套体系为例来具体说明传统的主备保持强一致性的一些问题。整个系统中主要包含如下几种角色:Master,Slave,Zookeeper-Service(zk),HA-Console(HA),Zookeeper-Agent(Agent)
Master,Slave:分别表示主节点和备节点,主节点提供读写服务,备节点能够提供读服务,或者彻底用于容灾。
Zookeeper-Service(zk):分布式一致性服务,负责管理Master/Slave节点的存活信息和切换信息。zk基于zab协议,zab协议是一种一致性协议,与paxos,raft协议相似,它主要有两种模式,包括恢复模式(选主)和广播模式(同步)。通常zk包含N个节点(zk-node),只要有超过半数的zk-node存活且相互连通,则zk能够对外提供一致性服务。
HA-Console:切换工具,负责具体的切换流程
Zookeeper-Agent(Agent):Master/Slave实例上的监听进程,与监听的实例保持心跳,维护Master/Slave的状态,每一个实例有一个对应的Agent。大概工做流程以下:
(1).Master/Slave正常启动并搭建好了复制关系,对应的Agent会调用zk接口去注册alive节点信息,假设分别为A和B。
(2).若是此时Master Crash,则实例对应的Agent发现心跳失败,若是重试几回后仍然失败,则将调用zk接口注销掉A节点信息。
(3).HA工具经过zk接口比较两次的节点信息,发现少了A节点,表示A可能不存在了,须要切换,尝试链接A,若是仍然不通,注册A的dead节点,并开始切换流程。
(4).HA工具读取配置信息,找到对应的Slave节点B,(更改读写比配置信息,设置B提供写),打开写。
(5).应用程序经过拉取最新的配置信息,得知新主B,新的写入会写入B。
前面几部基本介绍了MySQL借助zk实现高可用的流程,因为zk-node能够多地部署,HA无状态,所以能够很容易实现同城或者是异地的高可用系统,而且动态可扩展,一个HA节点能够同时管理多个Master/Slave的切换。那么能保证一致性吗?前面提到的Agent除了作监听,还有一个做用是尽量保持主备一致,而且不丢数据。
(6).假设此时A节点重启,Agent检测到,经过zk接口发现A节点在dead目录下,表示被切换过,须要kill上面的全部链接,并回滚crash时A比B多的binlog,为了尽量的少丢数据,而后再开启binlog后,将这部分数据重作。这里要注意rollback和replay都在old-Master上面进行,rollback时须要关闭binlog,而replay须要开启binlog,保证这部分数据能流向new-Master。
(7).从第6步来看,能够必定程度上保证主备一致性,可是进行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超时时间,以及选主的时间和日志恢复时间。

参考文档

https://ramcloud.stanford.edu/~ongaro/userstudy/paxos.pdf

http://www.cs.utexas.edu/users/lorenzo/corsi/cs380d/papers/paper2-1.pdf
http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf
https://zhuanlan.zhihu.com/p/20417442
http://my.oschina.net/hgfdoing/blog/666781
http://www.cnblogs.com/foxmailed/p/5487533.html
http://www.wtoutiao.com/p/1a7mSx6.html

相关文章
相关标签/搜索