一、协议概述
两阶段提交协议(2-phase-commit protocol,2PC)可以保证数据的强一致性,许多分布式关系型数据管理系统采用此协议来完成分布式事务。它是协调所有分布式原子事务参与者,并决定提交或回滚的分布式算法。也是解决一致性问题的一致性算法。为了能够使参与者从故障在恢复,采用日志记录协议的状态,虽然使用日志降低了性能但是节点能从故障中恢复。
在2PC中,系统一般含两类节点:
① 协调者 coordinator,通常一个系统中只有一个
② 参与者 workers,一般含多个,在数据存储系统中可以理解为数据副本的个数
协议中假设:
① 每个节点都记录写前日志并持久性存储,即使节点故障日志也不会丢失
② 节点不会发生永久性故障且任意两个节点间可以相互通信
当事务最后一步完成,协调者执行协议,参与者根据本地事务,能够成功完成回复同意提交事务或者回滚事务。
二、执行过程
两阶段提交由两个阶段组成:
1. 请求阶段(commit-request phase)
在此阶段,协调者通知事务参与者准备提交或回滚事务,然后进入表决过程:在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或回滚(本地作业执行故障)
2. 提交阶段(commit phase)
在该阶段,协调者基于第一个阶段的结果进行决策:提交或取消。当且仅当所有参与者回复同意,才通知所有事务参与者提交事务,否则协调者将通知事务参与者回滚事务。参与者在接收到协调者发来的消息后执行相应的操作。
三、协议的特点
两阶段提交系统通过阻塞完成协议,在节点等待消息的时候处于阻塞状态,节点中其他进程需等待阻塞进程释放资源才能使用。如果协调器发生了故障,那么事务参与者则会一直等待。以下情况可能会导致节点发生永久阻塞:
(1) 参与者发送同意提交消息给协调者,进程将阻塞直到协调者发消息。若协调者永久故障,参与者将一直等待。此问题可通过备份协调器解决。
(2)若协调器发送“请求提交”给所有参与者,它将被阻塞直到所有参与者回复。若某参与者永久故障,那么协调器也不会一直阻塞。在某一时间内还未收到某参与者消息,它将通知其他参与者回滚事务。
2PL没有容错机制,一个节点故障整个事务都回滚,代价较大。
四、工作过程
通过一个例子说明两阶段提交协议的工作过程:
A是保险公司销售小组组长,负责召开会议,B,C,D是苦逼的保险推销员。公司规定由组长召开小组会议,必须全员到场。A在星期六晚上发送下周一召开会议的通知给B,C,D。如果所有人周一都有时间来开会,那么会议将如期开展;若有任何一个有事不能在现场,则会议取消另定时间。用2PC算法解决过程:
A是协调者,B,C,D是该会议的参与者:
(1)请求阶段:
① A发送邮件给B,C,D,通知周一举行会议,询问是否都能到场。A此时等待B,C,D的回复邮件
② B,C,D分别查看自己的日程按排。B,C发现周一没有约见客户的日程安排,身为苦逼的员工当然得去开会!于是发邮件告诉A,会按时到场。由于某种原因,D白天没有查看邮件。那么此时A,B,C都需要等待。到晚上D发现了A的邮件,查看自己的日程安排,发现周一正好要去见客户,那么D就回复A:我要出外勤,无法参会,会议能不能改天?
(2)提交阶段(commit phase)
① A已经收到所有参与者的邮件,发现D因为公事无法参加周一的会议,于是 A发邮件通知 B,C,D。下周一的会议取消。
② 此时 B,C心里乐开了花,不用开会。至此事务结束。
通过上面的例子可以发现,2PC存在一定问题。如果D一直不回复邮件,那么A,B,C将一直处于等待状态。而且B,C所持有的资源,即周一不可以安排其他活动(见客户,上门推销保险…),一直不能释放。其他等待该资源释放的活动也不得不处于等待状态。
部分引用自:https://www.cnblogs.com/sunddenly/articles/4072882.html