一致性协议和paxos算法

本文深入探讨了集中式和分布式系统架构的区别,分析了分布式系统面临的挑战,如通信异常、网络分区和节点故障等。介绍了CAP和BASE理论在分布式系统设计中的应用,对比了一致性、可用性和分区容错性的权衡。详细解析了二阶段提交(2PC)、三阶段提交(3PC)和Paxos算法等一致性协议,以及它们在解决分布式一致性问题上的优势与局限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集中式和分布式的架构

所谓的集中式系统就是由由一台或多台主计算机组成中心节点,数据集中存储于这个中心节点,整个系统的所有业务单元都集中部署在这个中心节点上,系统的所有功能均由其集中处理。集中式系统最大的特点就是部署结构简单。由于集中式系统往往基于底层性能卓越的大型主机,因此无须考虑如何对服务进行多个节点的部署,也就不用考虑多个节点之间的分布式协作问题。

分布式系统是一个硬件活软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统,严格的说,一个分布式系统的计算机在空间部署上可以任意分布,可以在不同的机柜,不同的机房甚至不同的城市。

 

分布式环境面临的问题

通信异常:分布式系统需要在各个节点之间进行网络通信,因此会伴随网络不可用的风险,包括网络光纤,路由器或是DNS等硬件设备等风险故障,即使分布式各节点之间的网络通信正常,其延迟也会大于单机的操作数百倍,消息丢失和延迟变得非常普遍

网络分区:由于各节点之间的网络延迟不断增大,最终可能导致组成分布式系统的部分节点无法正常通行,称之“网络分区”,俗称“脑裂”,并由此引发各种数据一致性的问题。数据超时等问题

节点故障:分布式系统中的部分服务节点出现宕机等问题,导致系统不可用。

分布式事务:分布式事务指的是事务的参与者,支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点上,通常一个分布式事务中会涉及多个数据源或业务系统的操作,在单机服务中我们很容易实现一套满足ACID特性的事务处理系统,在但分布式数据服务中,由于数据节点可能分布在不同的机器上,各个子事务的执行就是分布式的,实现一种能够保证ACID的分布式事务处理系统显得格外复杂

 

CAP和BASE理论

CAP理论

2000 年 7 月,来自加州大学伯克利分校的 Eric Brewe 教授在 ACM PODC会议上,首次提出著名的 CAP 猜想,2 年后,来自麻省理工学院的Seth Gilbert 和 Nancy Lynch 从理论上证明了 Brewer 教授 CAP 猜想的可行性, CAP 理论正式在学术上成为了分布式计算领域的公认定理,并深深地影响了分布式计算的发展

CAP 理论:一个分布式系统不可能同时满足一致性(Consistency )、可用性 ( Availability )和分区容错性(Partition Tolerance)这三个基本需求,最多只能同时满足其中2项

一致性Consistency :

在分布式环境中,一致性是指数据在多个副本之间能够保持一致的特定,在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态(如对第一个节点对数据进行更新操作并且更新成功,却没有对第二个节点的数据更新导致第二个节点在读取数据时候读取的是脏数据,这就是典型的分布式数据不一致情况),在分布式系统中如果能够做到针对一个数据的更新执行成功后所有用户都可以读取最新的数据,那么认为这样的系统具有强一致性

可用性Availability :

可用性指系统提供的服务必须一致处于可用的状态,对于用户的每个操作都会在有限的时间内返回结果

分区容错性Partition Tolerance:

分区容错性指分布式系统在遇到任何网络分区故障时候,仍然需要能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生故障(网络分区指分布式系统中不同节点由于分布在不同的子网络,由于特殊原因而导致子网络之间出现网络不通的状态,但是各个子网络内部网络是正常的,从而导致整个系统的网络环境被切分若干个孤立的区域)

CAP理论的应用

序号放弃CAP说明
1放弃P,满足AC如果希望能够避免系统出现分区容错性问题,可以将数据和服务都放在一个节点上(或仅仅是哪些与事务有关的数据),可以避免因网络引起的负面影响,充分保证系统的可用性和一致性。但放弃P意味着放弃了系统的可扩展性
2放弃A,满足PC当节点故障或者网络故障时,受到影响的服务需要等待一定的时间,因此在等待时间里,系统无法对外提供正常服务,即是不可用的
3放弃C,满足AP这里的放弃一致性是指数据的强一致性,而保留系统的最终一致性,系统无法保证数据的实时一致性,但是承诺数据最终会保证一致性。因此存在数据不一致的窗口期,至于窗口期的长短取决于系统的设计,主要包括数据副本在不同节点之间复制时间的长短

从CAP理论中,我们可以看出一个分布式系统不可能同事满足一致性、可用性和分区容错性,另一方面,需要明确的是,对于一个分布式系统而言,分区容错性可以说是一个基本的要求,因为分布式系统中的组件必然会被部署到不同的节点,否则就无所谓什么分布式系统了,也就必然出现子网络和网络问题,因此分区容错性成了分布式系统必然需要面对解决的问题,而需要根据业务特点在C(一致性)和A(可用性)之间寻求平衡,所以一般分布式系统是满足AP或者CP的。

 

BASE理论

BASE是Basically Available (基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写,是由eBay的架构师Dan Pritchett提出,BASE理论是对CAP中一致性和可用性权衡的结果,来源于大规模互联网系统分布式实践的总结,基于CAP演化而来,核心思想是:即使无法做到强一致性(Strong consistency),但每次应用都可以根据自身业务特点,采用适当的方式使系统达到最终一致性(Event consistency)。

基本可用

基本可用指分布式系统出现不可预知的故障时候,允许损失部分可用性(这不等价系统不可用,而是比如:响应时间的损失,原来0.5s返回响应,现在需要1-2s,或功能的损失,在大并发请求下部分用户被引导到降级页面)

软状态

允许系统中数据存在中间状态,中间状态的存在不影响系统整体的可用性,即允许系统在不同节点的数据副本之间进行同步的过程存在延时

最终一致性

最终一致性强调的是系统中的所有数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态,因此最终一致性的本质是需要系统保证数据最终一致而不是实时一致的强一致性

总的来说,BASE理论面向的是大型高可用可扩展的分布式系统,和传统事务的ACID特性是想法的,不同于ACID的强一致性模型,而是通过牺牲强一致性来保证可用性,允许数据一段时间内不一致,而保证最终的一致性。

 

一致性协议

对一个分布式系统进行架构设计的过程中,在系统的可用性和数据一致性之间需要进行反复的权衡,为了解决分布式一致性的问题,出现许多经典的一致性协议和算法,主要有:二阶段提交协议、三阶段提交协议和Paxos算法等

 

2PC和3PC协议 

在分布式系统中,每一个机器节点虽然都能够明确地知道自己在进行事务操作过程中的结果是成功或失败,但却无法直接获取到其他分布式节点的操作结果。因此,当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的 ACIO 特性,就需要引入一个称为“协调者”( Coordinator) 的组件来统一调度所有分布式节点的执行逻辑,这些披调度的分布式节点则被称为“参与者” ( Participant )。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。基于这个思想,衍生出了二阶段提交和三阶段提交两种协议

2PC

2PC是Two-Phase Commit的缩写,即二阶段提交,通常二阶段提交协议被认为是一种一致性协议,用来保证分布式系统数据的一致性,目前绝大多数关系型数据库都采用的是二阶段提交协议来完成分布式事务处理的,该协议可以方便的完成分布式事务参与者的协调统一决定事务的提交或回滚,有效的保证分布式数据一致性,广泛的应用于分布式系统,主要分为二阶段来处理,流程如下

阶段一:提交事务请求(投票阶段)

事务询问:协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并等待参与者响应;

执行事务:各参与者执行事务操作,记录Undo和Redo信息到事务日志;

反馈事务询问的响应:如果参与者成功执行事务操作,反馈YES响应,表示事务可以执行,否则返回NO表示事务不可以执行

 

阶段二:执行事务的提交(根据参与者的响应决定是否执行事务提交)

情况一:执行事务提交,即所有参与者反馈YES响应,则执行事务提交

发送提交请求:协调者向所有参与者节点发送Commit请求

事务提交:收到Commit请求后,执行事务提交操作,提交完成后释放事务资源

反馈事务提交结果:事务提交后,向协调者发送ACK消息

完成事务:协调者接收到所有参与者反馈的ACK消息后,完成事务

 

情况二:中断事务,即存在任何一个参与者向协调者反馈了NO响应,或等待超时后还未收到所有参与者的反馈响应

发送回滚请求:协调者向所有参与者节点发出Rollback请求

事务回滚:参与者收到Rollback请求后,利用一阶段记录的Undo信息执行事务回滚操作,完成回滚后释放资源

反馈事务回滚结果:回滚完成后,向协调者发送ACK消息

中断事务:收到所有参与者返回的ACK消息后,完成事务中断

 

二阶段“事务提交”示意图如下:

二阶段“事务回滚”示意图

2PC的优缺点

优点:原理简单,实现方便

缺点:同步阻塞,单点问题,脑裂,过于保守

同步阻塞

二阶段提交过程中,所有参与该事务操作的逻辑都处理阻塞状态,各个参与者在等待其他参与者的响应过程中无法进行其他的任何操作,极大的限制分布式系统的性能

单点问题

协调者在二阶段提交过程中起到非常重要的左右,一旦协调者出现问题,二阶段流程无法运转,并且其他参与者将会一直处于锁定事务资源的状态无法继续完成事务操作

数据不一致

在二阶段提交的阶段二,协调者向所有的参与者发送Commit请求后,发生局部网络异常或者尚未发送完Commit请求自身发生崩溃,导致只有部分参与者收到Commit请求,从而导致部分事务提交部分事务无法提交,继而引起数据不一致的现象

太过保守

对于参与者出现故障而无法响应,协调者只有利用超时来决定是否中断事务,这种策略显得比较保守,换句话说二阶段提交没有完善的容错机制,任何一个节点的失败都导致整个事务的失败。

 

3PC协议

3PC是Three-Phase Commit的缩写,即三阶段提交,它是二阶段提交的改进版,将二阶段提交协议的“提交事务请求”过程一分为二,形成了由CanCommit、PreCommit和DoCommit三个阶段组成的事务处理协议

阶段一:CanCommit

事务询问:协调者向所有参与者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作,并等待各参与者的响应

反馈询问响应:参与者接收来自协调者的canCommit请求后,正常情况下,如果认为可以顺利执行事务则反馈YES响应并进入预备状态,否则反馈NO状态

 

阶段二:PreCommit

协调者会根据参与者的反馈情况来决定是否可以进行事务的PreCommit操作,正常情况下,包含2种可能

执行事务预提交(协调者得到所以参与者的反馈都是YES)

发送预提交请求:协调者向所有参与者节点发送preCommit的请求,并进入Prepared阶段

事务预提交:参与者收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中

反馈事务执行:参与者成功执行事务操作,反馈ACK响应给协调者,等待最终的提交或者中止指令

 

中断事务(协调者得到任何一个参与者反馈的NO响应或者等待超时没有收到所有参与者的反馈)

发送中断请求:协调者向所有参与者节点发出abort请求

中断事务:无论收到协调者的abort请求还是等待协调者请求过程中出现超时,参与者都会中断事务

 

阶段三:doCommit

执行提交

 

发送提交请求:协调者正常工作且收到所有参与者的ACK,从预提交状态转换到提交状态,向所有参与者发送doCommit请求

事务提交:参与者收到doCommit请求后,执行事务提交操作,完成后释放事务资源

反馈事务提交结果:参与者在完成事务提交后,向协调者发送ACK消息

完成事务:协调者接收到所有参与者反馈的ACK后,完成事务

 

中断事务

协调者正常工作且收到任意一个参与者反馈的NO,或者等待超时后且无法接收到所有参与者反馈的响应,则会中断事务

发送中断请求:协调者向所有参与者节点发送abort请求

事务回滚:参与者接收到abort请求后,利用阶段二中记录的Undo信息执行回滚操作,回滚后释放整个事务占用的资源

反馈事务回滚结果:参与者完成回滚后,向协调者发送ACK响应

中断事务:协调者接收到所有的ACK消息后,中断事务

注意:进入阶段三,如果出现以下两种故障:

  • 协调者出现问题
  • 协调者和参与者网络出现问题

都会导致参与者无法及时收到来自协调者的doCommit或者abort请求,参与者都会在等待超时后,继续进行事务提交

3PC的优缺点

相较于二阶段的提交协议,三阶段的提交协议最大的优点就是降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致

缺点就是去除阻塞的同时引入了新的问题,那就是在参与者接收到preCommit消息后,如果网络出现分区,协调者参与者无法通信,此时参与者依然会进行事务提交,从而导致数据不一致

 

Paxos算法

Paxos算法是有Leslie Lamport于1990年提出的一种基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一

一个分布式算法最重要的2个属性:安全性(Safely)和活性(liveness),简单来说,Safely是指那些需要保证永远都不会发生的事情,liveness是指那些最终一定会发生的事情

要解决的问题及应用场景

解决的问题:

在常见的分布式系统中,总会发生诸如机器宕机或者网络异常等情况,Paxos算法需要解决的就是如何在一个可能发生上述异常的分布式系统中,保证集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性
其典型应用场景为:

在一个分布式系统中,如果各节点初始状态一致,而且每个节点执行相同的命令序列,那么最后就可以得到一个一致的状态。为了保证每个节点执行相同的命令序列,即需要在每一条指令上执行一致性算法(如Paxos算法),来保证每个节点指令一致。
 

Paxos中的角色和约定   

Paxos算法的目标是为了保证最终有一个提案会被选定,且当提案选定后,进程最终也能获取到被选定的提案,在该一致性算法中,有以下3参与个角色:
Proposer:提案发起者,为了就某一个值达成一致,Proposer可以以任意速度、发起任意数量的提案,可以停止或重启。
Acceptor:提案批准者,负责处理接收到的提案,响应、作出承诺、或批准提案。
Learner:提案学习者,可以从Acceptor处获取已被批准的提案。

Proposal:为了就某一个值达成一致而发起的提案,包括提案编号和提案的值。

Paxos需要遵循如下约定:
1、一个Acceptor必须批准它收到的第一个提案。
2、如果编号为M0、value值为V0的提案(即[ M0,V0])的提案被批准了,那么所有比编号M0更高的,且被选定的提案,其value值必须也是V0

 

提案的选定

Proposer向一个Acceptor集合发送提案,当有足够多的的Acceptor批准这个提案时,就认定提案被选定,此外还规定每个Acceptor最多只能批准一个提案,这样就可以保证只有一个提案被选定了。(这里的足够多的Acceptor是整个Acceptor的子集,这个子集包含Acceptor集合中的大多数,又因为任意两个包含大多数Acceptor的子集至少有一个公共成员,所以这里的足够多至少是超过一半数量的Acceptor)

Proposer生成提案

Proposer在产生一个编号为Mn的提案时,必须要知道当前某一个将要或者已经被半数以上Acceptor批准的编号小于Mn但为最大编号的提案,并且Proposer会要求所有的Acceptor都不再要批准任何编号小于Mn的提案,提案生成算法如下:

1、Proposer选择一个新的提案编号Mn,然后向某个Acceptor集合成员发送请求,要求该集合中的Acceptor做出如下回应

  • 向Proposer承诺,保证不再批准任何编号小于Mn的提案
  • 如果Acceptor已经批准过了任何提案,就向Proposer反馈当前该Acceptor已经批准的编号小于Mn但为最大编号的那个提案的Value值

2、如果Proposer收到来自半数以上的Acceptor的响应结果,那么它就可以产生编号为Mn、Value值为Vn的提案了,这里的Vn是所有响应中编号最大的提案的Value值,当然如果半数以上的Acceptor都没有批准过任何的提案,即响应中不包含任何提案,此时的Vn的值可以由Proposer任意选择

在确认提案之后,Proposer就会将该提案再次发送给某个Accpetor集合,获取批准,称此次请求为Accpect请求,需要注意的是:接收Acceptor请求的Acceptor集合不一定是之前相应Prepare请求的Acceptor集合

Acceptor批准提案

一个Acceptor可能会收到自来Proposer的两种请求:分别是Prepare请求和Accept请求,并对两类请求作出相应的条件如下

  • Prepare请求:Acceptor可以在任何时候相应一个Prepare请求
  • Accept请求:在不违背Acceptor现有的承诺前提下,可以任意响应Accept请求,一个Acceptor只要尚未响应过任何编号大于Mn的Prepare请求,那么它就可以接受这个编号为Mn的提案(这个提案的值可能是Acceptor反馈的或者是Proposer任意选择的)

假设一个Acceptor收到一个编号为Mn的Prepare请求,但此时该Acceptor已经对编号大于Mn的Prepare请求做出了响应,因此他不会在批准编号为Mn的提案了,Acceptor也没有必要对这个Prepare请求做出响应,所以Acceptor选择忽略这个Prepare请求,同时Acceptor也忽略掉哪些它已经批准过的提案的Prepare请求。这样的话,每个Acceptor只需要记住它已经批准的提案的最大编号以及它已经做出Prepare请求响应的提案的最大编号即可。

算法描述

阶段一

  1. Proposer选择一个提案编号Mn,然后向Acceptor的某个超过半数的子集成员发送编号为Mn的Prepare请求
  2. 如果一个Acceptor收到一个编号为Mn的Prepare请求,且编号Mn大于该Acceptor已经响应的所有Prepare请求的编号,那么Acceptor会将它已批准过的最大编号的提案作为响应反馈给Proposer,同时该Accpetor会承诺不会在批准任何编号小于Mn的提案了

demo:假如一个Acceptor已经响应过提案编号为1,2,3,4,5,7的Prepare请求,该Acceptor在接受到一个编号为8的Prepare请求后,就会将编号为7的提案最为响应反馈给Proposer

阶段二

  1. 如果Proposer收到来自半数以上的Acceptor对于其发出的编号为Mn的的Prepare请求的响应,那么该Proposer就会发送一个针对 [ Mn,Vn ]提案的Accept请求给Acceptor,注意Vn的值就是收到的所有响应中编号最大的提案的值,如果响应中不包含任何提案,那么它就是任意值
  2. 如果Acceptor收到这个针对[ Mn,Vn ]提案的Accept请求,只要该Acceptor尚未对编号大于Mn的Prepare请求做出响应,它就会通过该提案

当然,在实际运行过程中,每一个Proposer都有可能产生多个提案,每个Proposer都可以在任意时刻丢弃一个提案,哪怕该提案的请求和响应马上就会达到;此外Acceptor在收到更大编号的Prepare请求也会忽略编号更小的Prepare或Accept请求,并且通知其对应的Proposer,以便Proposer也能够对该提案就行丢弃。

提案的获取

上面已经知道如何选定一个提案,那么Learner如何获取提案呢?主要有以下几种方案:

方案一:

Learner获取已经被选定方案的前提是该提案被半数以上的Acceptor批准,因此最简单的方案就是一旦一个Acceptor批准了一个提案,就把该提案发送给所有Learner,该方案可以快速获取选定的方案,但是每个Acceptor和所有的Learner逐个通信,通信次数至少为二者的乘积。

方案二:

所有的Acceptor将他们对提案的批准情况统一发送给特定的Learner(主Learner),在不考虑消息篡改的前提下,各个Learner之间可以通过消息通信感知提案选定情况,该提案虽然比方案一多了一个步骤,但是通信次数减少了,通信次数是Acceptor和Learner的总和,同时引入新问题就是:主Learner的单点问题

方案三:

基于方案二的单点问题,可以把主Learner替换成特定的Learner集合,集合中的每个Learner都可以在提案被选定后通知其他Learner,集合的Learner个数越多,可靠性越好,通信复杂度越高

保证算法活性

通过选取主Proposer来保证算法活性,假设存在一种极端情况,两个Proposer依次提出一系列编号递增的议案,但是最终都无法被选定,流程如下:

Proposer1提出一个 编号为M1的提案,完成阶段1流程,与此同时,Proposer2提出一个编号为M2(M2>M1)的提案,同样完成阶段一的流程,因此当P1进入阶段二的时候,发出的Accept请求将被Acceptor忽略,于是P1再次进入阶段一并提出一个编号为M3(M3>M2)的提案,而这导致P2的第二阶段的Accpet请求被忽略,以次类推,提案的选定陷入死循环

为了保证Paxos算法的可持续性,必须选择一个主Proposer,并规定只有主Proposer才能提出议案,这样只要主Proposer和过半的Proposer能够正常通信,那么凡是主Proposer提出一个编号更高的提案,该提案将会被批准,并且丢弃编号较小的提案,并最终选择编号足够大的提案,因此通过选择一个主Proposer可以使Paxos算法流程保持活性

 

一致性协议的总结

二阶段提交协议解决了分布式一书务的原子性问题,保证了分布式事务的多个参与者要么都执行成功,要么都执行失败。但是,在二阶段解决部分分布式事务问题的同时,依然存在一些难以解决的诸如同步阻塞、无限期等待和“脑裂”等问题。三阶段提交协议则是在二阶段提交协议的基础上,添加了 PreCommit 过程,从而避免了二阶段提交协议中的无限期等待问题。而 Paxos 算法引入了“过半”的理念,通俗地讲就是少数服从多数的原则。 同时, Paxos 算法支持分布式节点角色之间的轮换,这极大地避免了分布式单点的出现,因此 Paxos 算法既解决了无限期等待问题,也解决了“脑裂”问题,可以说是最优秀的分布式一致性协议之一

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值