2PC:two phase commit 二阶段提交协议
2pc是在计算机网络以及数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务的提交时,保持一致性而设计的一种算法。通常,二阶段提交也被称为是一种协议。
在分布式系统中,每个节点虽然可以知晓自己的操作是否成功,但无法知道其他节点的操作是否成功。当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为协调者的组件来统一掌控所有的节点的操作结果,并最终指示这些节点是否要把操作结果真正的提交。(每个节点也称为参与者)
其算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈结果决定所有的参与者是否要提交操作还是终止操作。所有的节点都投票决定是否执行事务操作。
二阶段提交协议:把事务的提交过程分为两个阶段来进行处理。
- 第一阶段:投票阶段 / 准备阶段
1. 事务询问。(协调者 --> 参与者)
事务协调者(事务管理器)向每个事务参与者(资源管理器)询问,是否准备好了执行事务,并开始等待各个参与者的响应。
2. 执行事务。( 参与者)
各个参与者节点执行事务操作,并将Undo和Redo信息记入到事务日志中。【注意:若成功这里其实每个参与者已经执行了事务操作】
3. 各参与者向协调者反馈事务查询的统计。(参与者 --> 协调者)
各个参与者响应协调者发起的询问。若参与者节点的事务操作实际执行成功,则返回一个“同意”消息;如果参与者节点的事务操作实际执行失败,则返回一个“终止”消息。
- 第二阶段:提交阶段 / 执行阶段
根据投票结果执行两种操作:执行事务提交或者中断事务。
- 执行事务提交:协调者节点从所有的参与者节点获得的消息都为“同意”。
- 协调者节点向所有的参与者节点发出“正式commit”请求。
- 参与者节点正式完成操作,释放在整个事务期间内占用的资源。
- 参与者节点向协调者节点发送“完成”消息。
- 协调者节点收到所有参与者节点的“完成”消息后,完成事务。
- 中断事务:任一参与者节点在一阶段的响应消息为“终止”,或者一阶段询问超时无法获取所有参与者节点的响应消息。
- 协调者节点向所有的参与者节点发出“回滚操作”请求。
- 参与者节点利用之前写入的Undo信息执行回滚操作,并完成操作之后释放在整个事务期间内占用的资源。
- 参与者向协调者节点发送“回滚完成”消息。
- 协调者节点收到所有参与者节点反馈的“回滚完成”消息后,取消事务。
缺点:
同步阻塞、单点问题、数据不一致、过于保守。
同步阻塞:
执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
单点问题:
由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
数据不一致:
在二阶段提交阶段中,当协调者向参与者发送commit请求之后,发生了局部的网络异常或者在发送commit请求的过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
过于保守:
二阶段提交协议没有设计较为完善的容错机制,任意一个节点的失败都会导致整个事务的失败。
参考:
分布式系统一致性算法:https://blog.csdn.net/wuxians/article/details/81275441
分布式理论(三)—— 一致性协议之 2PC:https://www.cnblogs.com/stateis0/p/9062126.html