分布式事务一致性的保证 2PC和3PC和PAXOS

本文深入探讨了分布式事务处理中的经典算法,包括两阶段提交(2PC)、三阶段提交(3PC)以及PAXOS算法。2PC在协调者故障时可能导致数据不一致和资源长时间锁定;3PC通过引入超时机制缓解了这些问题,但仍有同步堵塞和数据不一致的风险。PAXOS算法通过日志同步确保节点间一致性,解决并发提案冲突,但也面临活锁问题。文章对比了这些算法的优缺点,并提出了多轮提案的Multipaxos优化方案。
摘要由CSDN通过智能技术生成

2PC

两阶段提交,包含两个角色(协调者与参与者)
分为准备阶段以及提交阶段

准备阶段

  1. 协调者发送提交请求给各个参与者
  2. 参与者执行事务,并记下undo,redo日志
  3. 执行者将执行结果告诉协调者

提交阶段

第一阶段中所有的参与者均执行成功
  1. 协调者发送提交信息
  2. 参与者执行事务提交
  3. 参与者发送提交完成消息
  4. 执行者向各个参与者发送执行完成消息
第一阶段中存在执行失败的参与者
  1. 协调者发送回滚信息
  2. 参与者执行事务回滚
  3. 参与者发送回滚完成消息
  4. 执行者向各个参与者发送回滚完成消息

2PC存在的问题

  • 同步堵塞:两个事务竞争同
  • 单点问题: 协调者在提交阶段如果出事,则参与者会一直持有资源
  • 数据不一致:在提交阶段,如果只有一部分commit消息发出去之后,协调者就挂掉了
  • 过于保守:任何一个参与者出现问题,都会影响整个事务的进程

3PC

三阶段提交,主要是解决了2PC没有处理的超时响应问题。

canCommit阶段

协调者发送canCommit消息,然后等待参与者响应
参与者收到消息后,根据自身状况(是否可以正常执行事务),返回yes(进入预备状态)或者no

preCommit阶段

均返回yes
  1. 协调者发送preCommit请求,并进入prepare阶段
  2. 参与者收到消息后,执行事务,并记录下redo,undo日志
  3. 参与者若执行成功,返回一个ack,并等待下阶段的指令
存在返回no或者是超过响应等待时间的
  1. 协调者发送中断请求(abort请求)
  2. 参与者收到协调者发送的abort请求后(或者超时未得到响应),执行事务中断。

doCommit阶段

执行提交
  1. 协调者给参与者发送commit消息。
  2. 参与者提交事务,并释放占有的资源。
  3. 参与者成功提交后,向协调者发送ack响应。
  4. 协调者收到所有参与者发送的事务执行成功消息后,完成事务。
执行中断
  1. 协调者向所有参与者发送abort请求
  2. 参与者利用二阶段的undo信息执行事务回滚操作,并在完成回滚后释放所有资源
  3. 参与者完成回滚后,想协调者发送ack响应
  4. 协调者收到所有参与者的相应后,执行事务中断

3PC存在的问题

  • 同步堵塞:竞争相同的资源,会造成堵塞,但是由于存在超时机制,所以可以减少堵塞的时间。
  • 数据不一致:在doCommit阶段,如果协调者发送了abort但是参与者等待响应超时自动提交了事务,则会造成不一致。

2PC和3PC比较

3PC的优点

增加了超时机制

在等待precommit阶段如果超时,则中断事务,减少了堵塞的时间,2pc则是一直等待协调者的commit和abort命令。
在等待commit阶段如果超时,则提交事务,因为经过了cancommit和precommit阶段后,事务成功几率大,所以选择相信提交事务。

增加了一个canCommit阶段

主要是为了doCommit阶段的超时自动提交做铺垫,增加了一个阶段之后,可以增加事务的成功概率。第一个阶段已经说明了节点之间通信是没问题的了

PAXOS (帕克索斯)

为了解决这么一个问题

在这里插入图片描述

client1,client2,client3分别往node1,node2,node3发送设置x请求的时,如何保证node1,node2,node3上的最终get(x)的结果一致。

解决方案

各个节点之间互相同步日志流(变化过程),而非状态机(结果)。
这样即使节点宕机,只要重启并重放日志流,也能恢复结果。
这种初始状态 + 日志流的同步方式也叫复制状态机。即一样的初始状态 + 一样的日志流 = 一样的最终状态。
因此,最终的解决方案就是复制日志!复制日志=复制任何数据(复制任何状态机)。因为任何复杂的数据(状态机)都可以通过日志生成!

解决过程

如何让三个节点中写入的设置x值的日志完全一致呢
首先已一个递增的日志序号为基础,假设这个递增序号是从0开始的(当然只要是递增即可,没必要规律)
当node1收到消息后,先询问0号位置的日志记录是否被写入,没有则通知node2和node3,这个位置我占了,你们也和我一起把这条记录写进去。(类似2PC模型,先问再做)
当然这个过程也存在问题,当node1和node2在同时向其他节点发出日志写入的请求时,就会出现冲突,多个节点都想占用0号位置的日志记录。‘
basic paxos算法就是用来解决这个同时发起请求的冲突问题的。

basic paxos算法(每一次解决一次提案)

basic paxos下每个节点充当两个角色,分别为proposer(提议)以及acceptor(决议)
上述node1,node2,node3在收到设置x的请求后,分别向其他两个节点发起设置x的值为XXX的日志提议。
下面简单描述一下如何在各个节点之间互相同步日志流的过程。
该过程分为两个阶段,分别为prepare阶段以及accept阶段,

首先是准备工作
  1. minProposalId = acceptProposalId = 0
  2. acceptValue = null
接着介绍prepare所做的事情
  1. Proposer向所有acceptor发出proposal(n),其中n为提案编号,n可以直接以时间戳作为规则。
  2. 每个acceptor拿到proposal(n)后判断n和当前该acceptor选定的编号的大小关系。
  3. acceptor回复已经接收过的最大编号以及value,若为空则返回空。(部分acceptor已经接收了某个提案,不可更改)

在这里插入图片描述

然后介绍accept阶段做的事
  1. proposer向所有acceptor发出accept(n,v)。
  2. acceptor收到accept(n,v)后判断n和minProposalId的大小关系,若大于,则接收该填并返回。
  3. proposer判断时候收到了超过半数的yes,若有,则完成提案,否则重新开始prepare流程。
这里图画错了,应该是n < minProposalId以及n >= minProposalId

在这里插入图片描述

接下来介绍一些流程图中的判断规则

1、当一个acceptor已经接受了一个proposal(n,v)提案后,后续的proposal(a, b) a>n 的提案的值也会被改为v
即:如果某个值为value的提案已经被选定了,那么每个编号更高的被acceptor选中的提案的值也为value
(解决分区问题,这个问题在prepare阶段解决,因为prepare阶段会询问当前每个acceptor的提案接收情况)
在这里插入图片描述

其中A2,A3都已经接受了P2的提案,如果P1不先prepare一下,
就不知道其实其他acceptor已经接收了P2的提案,会导致A1接收错误的P1的提案
2、对于任意一个被接收的提案proposal(n,v),一定存在一个数量大于所有acceptor一半的集合S
S中的每个acceptor都没有接受过编号小于N的提案
S中接受过的最大编号提案

但是这个basic paxos算法有个活锁的问题

当两个线程相互提案的时候,在第一个线程未accept时,第二个线程进行了prepare,然后第一个线程再accept,就会导致accept失败。
然后此时若第二个线程挂起,第一个线程prepare,那么第二个线程accept的时候也会失败,长此往复,就会造成两个线程的活锁。
解决方案为
选举一个proposer的leader,只有leader可以提案,其他proposer的提案都应该转发给leader,由leader来发起。

那么如何解决选主时的活锁呢

Proposer执行Accept阶段失败时,不重新获取提案编号重新执行,直接抛弃该提案
Proposer执行Accept阶段失败时,等待一段时间再新获取提案编号重新执行
或者是 accept失败后,等一段时间再发起下次proposal

对于一轮提案是这么处理的,当升级到多轮提案时,有一个改良multi paxos算法

优化了rtt及数据持久化次数
本来prepare和accept阶段都需要一次rtt和一次数据持久化
multi paxos算法在选举出leader后,只会进行一次prepare,后边的提案都是直接accept
函数由
prepare(n)
accept(n,v)
改为
prepare(n,epoch) 一次
accept(n,v,epoch)
当leader故障时,选举出的新的leader会进行一次prepare,道是minProposalId变化,使旧的leader的广播失效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值