分布式领域两阶段(2PC)和三阶段(3PC)都是非常经典的概念,本文简单介绍下2PC和3PC的一些概念和优劣,做个记录。 #两阶段提交
两阶段提交用来保持在分布式系统架构里的原子性和一致性,关于事务特性见前文,本文后面的PPT里也有简单补充。 其中包含的角色为:协调者,参与者
###第一阶段
提交事务请求
- 询问 协调者向所有参与者发送事务内容,询问是否提交,开始等待响应。
- 执行 参与者执行事务操作,写undo 和 redo *1到事务日志,
- 参与者向协调者返回询问的响应
如果参与者成功执行了事务,反馈给协调者Yes,表示可以执行;如果参与者执行失败,返回给协调者No响应,表示不可以执行。
###第二阶段
执行事务提交#####结果1:成功执行提交 - 发送提交请求 协调者收到所有的Yes反馈,向所有参与者发送commit请求
- 事务提交 参与者收到协调者的commit请求,开始正式提交事务,完成提交后释放占用的事务资源
- 反馈提交结果 参与者完成正式提交之后,给协调者发送ACK响应
- 完成事务 协调者接收到所有参与者的ACK反馈后,完成事务 #####结果2:执行事务中断 1.发送回滚请求 协调者收到参与者No反馈,向所有参与者发送rollback请求 2.事务回滚 参与者接收到rollback请求,按照undo日志执行回滚,完成后释放占用的事务资源。 3.反馈回滚结果 参与者完成回滚后,给协调者发送ACK消息 4.中断事务 协调者接收到所有参与者的ACK消息后,完成整体事务的中断
两阶段的问题:
- 同步阻塞:一次事务请求中,参与者在等待其他参与者响应时无法做任何其他操作
- 单点问题: 协调者处于单点位置,尤其在第二阶段(提交或者中断)会导致资源锁定。如发生故障,参与者占有的资源无法释放。
- 数据不一致:在最终commit的过程中,如果发生网络故障或者其他原因导致只发送了部分commit,会造成只有部分执行了commit,产生数据的不一致,也有称作“脑裂”
- 设计太过保守:如果协调者无法获取参与者的信息,则只能通过自身的超时机制来确认是否中断事务,容错机制不是特别完善,任何一个节点失败都会导致整个事务的失败,失败影响的范围较大。 #三阶段提交 三阶段针对两阶段的缺点,做出改进,将2PC的第一阶段拆分,并且在协调者和参与者中都引入超时机制。
###第一阶段
请求提交canCommit
- 事务询问 协调者向所有参与者发送一个canCommit请求,询问是否可以执行事务提交操作。
- 各个参与者向协调者反馈询问的响应 参与者在收到canCommit询问请求后,确认是否可以执行事务,可以回复Yes,并进入预备状态;否则回复No响应。
###第二阶段
预备提交preCommit
#####结果1:在所有参与者回复Yes之后,执行事务预提交
- 协调者发送预提交请求 协调者向所有参与者发送PreCommit请求,协调者进入Prepare状态。
- 事务预提交 参与者收到preCommit之后,执行事务操作,写redo和undo信息到事务日志中。
- 反馈预提交结果 参与者如果成功执行了事务操作,反馈给协调者ACK响应,并等待协调者最终执行,commit或者abort(注意此处的commit或者abort是对preCommit的处理,不是最终提交)
#####结果2:中断preCommit,任何一个参与者向协调者发送No,或者协调者等待响应超时,则开始中断。
- 发送预中断请求 协调者向所有参与者发送abort请求。
- 中断事务 参与者收到协调者的abort请求,或者参与者等待请求超时,开始执行中断。
###第三阶段
正式提交doCommit
#####结果1:执行正式提交
- 发送正式提交请求 协调者正常工作,收到所有参与者的ACK响应,将从prepare转到commit状态,并向所有参与者发送doCommit请求。
- 事务正式提交 参与者接收到doCommit请求后,正式提交事务,并释放锁定的事务资源。
- 反馈正式提交结果 参与者如果成功执行了事务操作,反馈给协调者ACK响应,并等待协调者最终执行,commit或者abort(此处是正式提交阶段的commit或者abort)
- 完成事务 协调者接收到所有参与者的ACK消息之后,完成事务。
#####结果2:中断事务 只要协调者收到任意一个参与者的No响应,则开始中断事务
- 发送中断请求 协调者正常工作,向所有参与者发送abort请求。
- 事务回滚 参与者收到abort请求之后,利用undo信息执行事务回滚操作,完成后释放锁定的事务资源。
- 反馈回滚结果 参与者完成事务回滚之后,向协调者发送ACK消息
- 中断事务 协调者接收到所有参与者的ACK消息后,完成中断事务
三阶段的优劣:
- 减小了参与者阻塞的范围,在出现单点故障后仍然能达成一致。
- 和2PC类似,如果参与者收到preCommit之后,发送网络异常,参与者仍旧会执行事务提交,导致数据的不一致。
- 实现较为复杂
- 网络通信量大,会增高延迟
#2PC和3PC的图解
图片来自网络,可以作为简单分析了解。
两阶段:
三阶段:
相关介绍: redo和undo日志: redo日志用来重放,找到所有已经commit的事务,根据redo log重做,记>录在MySQL存储页的物理修改;undo用来回滚,找到所有uncommitted的事务,利用undo来回滚,记录逻辑的修改(insert->delete)。另外undo也有自己的redo日志。对应的过程参考下图,过程A先于过程B:
参考: 《从Paxos到Zookeeper》 《MySQL innodb存储引擎》 分布式两阶段,三阶段的理解:www.cnblogs.com/binyue/p/36… 分布式一致性到共识机制PAXOS:www.cnblogs.com/binyue/p/86… 分布式事务,两阶段,三阶段:www.hollischuang.com/archives/68…
演示的PPT整理:PPT