分布式系统原理

两阶段提交协议

两阶段提交协议是一种经典的强一致性中心化副本控制协议[2][3]。虽然在工程中该协议有较多的问题,但研究该协议能很好的理解分布式系统的几个典型问题。

1. 问题背景

两阶段提交(two phase commit)协议是一种历史悠久的分布式控制协议。最早用于在分布式数据库中,实现分布式事务。这里有必要首先简单介绍一下两阶段提交的最初问题背景,从而能更好的理解该协议。

在经典的分布式数据库模型中,同一个数据库的各个副本运行在不同的节点上,每个副本的数据要求完全一致。数据库中的操作都是事务(transaction),一个事务是一系列读、写操作,事务满足ACID。每个事务的最终状态要么是提交(commit),要么是失败(abort)。一旦一个事务成功提交,那么这个事务中所有的写操作中成功,否则所有的写操作都失败。在单机上,事务靠日志技术或 MVCC等技术实现。在分布式数据库中,需要有一种控制协议,使得事务要么在所有的副本上都提交,要么在所有的副本上都失败。对同一个事务而言,虽然在所有副本上执行的事务操作都完全一样,但可能在某些副本上可以提交,在某些副本上不能提交。这是因为,在某些副本上,其他的事务可能与本事务有冲突(例如死锁),从而造成在有些副本上事务可以提交,而有些副本上事务无法提交。本文不再深入讨论事务冲突的问题,只是将问题背景介绍情况,该类问题可以通过阅读经典的数据
库系统相关资料了解。

2. 流程描述

按本文的分类,两阶段提交协议是一种典型的“中心化副本控制”协议。在该协议中,参与的节点分为两类:一个中心化协调者节点(coordinator)和 N 个参与者节点(participant)。每个参与者节点即上文背景介绍中的管理数据库副本的节点。

两阶段提交的思路比较简单,在第一阶段,协调者询问所有的参与者是否可以提交事务(请参与者投票),所有参与者向协调者投票。在第二阶段,协调者根据所有参与者的投票结果做出是否事务可以全局提交的决定,并通知所有的参与者执行该决定。在一个两阶段提交流程中,参与者不能改变自己的投票结果。两阶段提交协议的可以全局提交的前提是所有的参与者都同意提交事务,只要有一个参与者投票选择放弃(abort)事务,则事务必须被放弃。

协议流程如下:

流程 2.6.1:两阶段提交协调者流程
1. 写本地日志“begin_commit”, 并进入 WAIT 状态;
2. 向所有参与者发送“prepare 消息”;
3. 等待并接收参与者发送的对“prepare 消息”的响应;3.1 若收到任何一个参与者发送的“vote-abort 消息”;3.1.1 写本地“global-abort”日志,进入 ABORT;3.1.2 向所有的参与者发送“global-abort 消息”;3.1.3 进入 ABORT 状态;3.2 若收到所有参与者发送的“vote-commit”消息;3.2.1 写本地“global-commit”日志,进入 COMMIT 状态;3.2.2 向所有的参与者发送“global-commit 消息”;
4. 等待并接收参与者发送的对“global-abort 消息”或“global-commit 消息”的确认响应消息,
一旦收到所有参与者的确认消息,写本地“end_transaction” 日志流程结束。
流程 2.6.2:两阶段提交协调者流程
1.写本地日志“init”记录,进入 INIT 状态
2.等待并接受协调者发送的“prepare 消息”,收到后2.1 若参与者可以提交本次事务2.1.1 写本地日志“ready”,进入 READY 状态2.1.2 向协调者发送“vote-commit”消息2.1.4 等待协调者的消息2.1.4.1 若收到协调者的“global-abort”消息2.1.4.1.1 写本地日志“abort”,进入 ABORT 状态2.1.4.1.2 向协调者发送对“global-abort”的确认消息2.1.4.2 若收到协调者的“global-commit”消息2.1.4.1.1 写本地日志“commit”,进入 COMMIT 状态2.1.4.1.2 向协调者发送对“global-commit”的确认消息2.2 若参与者无法提交本次事务2.2.1 写本地日志“abort”,进入 ABORT 状态2.2.2 向协调者发送“vote-abort”消息2.2.3 流程对该参与者结束2.2.4 若后续收到协调者的“global-abort”消息可以响应
3. 即使流程结束,但任何时候收到协调者发送的“global-abort”消息或“global-commit”消息
也都要发送一个对应的确认消息。

3. 异常处理

3.1 宕机恢复

两阶段提交协议中,使用了日志技术从而在宕机后可以恢复流程状态。这里简单分析一下两阶段提交试用日志做宕机恢复的过程。

3.1.1 协调者宕机恢复

协调者宕机恢复后,首先通过日志查找到宕机前的状态。

如果日志中最后是“begin_commit”记录,说明宕机前协调者处于 WAIT 状态,协调者可能已经发送过“prepare 消息”也可能还没发送,但协调者一定还没有发送过“global-commit 消息”或“global-abort 消息”,即事务的全局状态还没有确定。此时,协调者可以重新发送“prepare 消息”继续两阶段提交流程,即使参与者已经发送过对“prepare 消息”的响应,也不过是再次重传之前的
响应而不会影响协议的一致性。

如果日志中最后是“global-commit”或“global-abort”记录,说明宕机前协调者处于 COMMIT或 ABORT 状态。此时协调者只需重新向所有的参与者发送“global-commit 消息”或“global-abort消息”就可以继续两阶段提交流程。

3.1.2 参与者宕机恢复

参与者宕机恢复后,首先通过日志查找宕机前的状态。

如果日志中最后是“init”记录,说明参与者处于 INIT 状态,还没有对本次事务做出投票选择,参与者可以继续流程等待协调者发送的“prepare 消息”。

如果日志中最后是“ready”记录,说明参与者处于 REDAY状态,此时说明参与者已经就本次事务做出了投票选择,但宕机前参与者是否已经向协调者发送“vote-commit”消息并不可知。所以此时参与者可以向协调者重发“vote-commit”,并继续协议流程。

如果日志中最后是“commit”或“abort”记录,说明参与者已经收到过协调者的“global-commit消息”(处于 COMMIT 状态)或者“global-abort 消息”(处于 ABORT 状态)。至于是否向协调者发送过对“global-commit”或“global-abort”的确认消息则未知。但即使没有发送过确认消息,由于协调者会不断重发“global-commit”或“global-abort”,只需在收到这些消息时发送确认消息既可,不影响协议的全局一致性。

3.2 响应超时

协议主要的异常最终会体现在流程中“等待消息”超时上,即等待了一个足量长的时间后,不能接收到需要的消息,使得流程无法进行下去。下面逐一分析这些超时的原因和对协议的影响。

3.2.1 协调者在 WAIT 状态超时

协调者在 WAIT 状态状态超时,即协调者等待参与者对“prepare 消息”的响应超时,在超时时间内始终不能收到所有的参与者的投票结果而收到的响应都是“vote-commit”消息,从而协调者无法确定该事务是否可以提交。这种超时可能的原因有:

  1. 协调者与某个参与者网络中断,协调者的“prepare”消息无法发送到参与者,或者参与者的响应消息无法发送到协调者。
  2. 参与者宕机,如果某个参与者宕机,则无法响应协调者的“prepare 消息”,只有等该参与者恢复后才能响应消息。

对于这种超时,协调者可以选择直接放弃整个事务,向所有参与者发送“global-abort”消息,进入 ABORT 状态。由于协调者在超时前并没有发送任何“global-abort”或者“global-commit”消息,所以协调者此时放弃事务不影响协议的一致性。

3.2.2 协调者在 COMMIT 或 ABORT 状态超时

协调者在COMMIT或ABORT状态超时,即协调者等待参与者对“global-commit”或“global-abort”消息的响应时超时,从而协调者无法确认两阶段提交是否完成。这种超时可能的原因有:

  1. 协调者与某个参与者网络中断,协调者的“global-commit” 或“global-abort”消息无法发送到参与者,或者参与者的响应消息无法发送到协调者。
  2. 参与者宕机,如果某个参与者宕机,则无法响应协调者的“global-commit” 或“global-abort”,只有等该参与者恢复后才能响应消息。

对于这种超时,协调者只能不断重发“global-commit” 或“global-abort”消息给尚未响应的参与者,直到所有的参与者都发送响应。可以这么认为,两阶段提交协议对于这种超时的相关异常没有很好的容错机制,整个流程只能阻塞在这里,且流程状态处于未知。也许所有的参与者都完成了各自的流程,只是由于协调者无法收到响应,整个两阶段提交协议就无法完成。

3.2.3 参与者在 INIT 状态超时

参与者等待协调者的“prepare”消息时超时,此种异常的原因可能是协调者宕机或者协调者与参与者网络中断。对于这种超时,参与者可以进入 ABORT 状态,这样即使后续收到了“prepare”消息,也不影响协议的一致性也不会阻塞其他流程,唯一的缺点是,该事务可能原本可以提交,现在却被放弃。

3.2.4 参与者在 READY 状态超时

参与者在 READY 状态等待协调者发送的“global-commit”或“global-abort”消息超时。出现这种超时的原因可能是协调者宕机也可能是网络中断。

因为参与者处于 READY状态,说明参与者之前一定已经发送了“vote-commit”消息,从而参与者已经不能改变自己的投票选择。此时,参与者只能不断重发“vote-commit”消息,直到收到协调者的“global-commit”或“global-abort”消息后流程才可继续。可以这么认为,两阶段提交协议对于这种超时的相关异常也没有很好的容错机制,整个流程只能阻塞在这里,且对于参与者而言流程状态处于未知,参与者即不能提交本地节点上的事务,也不能放弃本地节点事务。

4. 协议分析

两阶段提交协议在工程实践中真正使用的较少,主要原因有以下几点:

第一、两阶段提交协议的容错能力较差。从上文的分析可以看出,两阶段提交协议在某些情况下存在流程无法执行下去的情况,且也无法判断流程状态。在工程中好的分布式协议往往总是可以在即使发生异常的情况下也能执行下去。例如,回忆 Lease 机制(2.3 ),一旦 lease 发出,无论出现任何异常,Lease 服务器节点总是可以通过时间判定出 Lease 是否有效,也可以用等待 Lease 超时的方法收回 Lease 权限,整个 Lease 协议的流程不存在任何流程被阻塞而无法执行下去的情况。与Lease 机制的简单有效相比,两阶段提交的协议显得较为复杂且容错能力差。

第二、两阶段提交协议的性能较差。一次成功的两阶段提交协议流程中,协调者与每个参与者之间至少需要两轮交互 4 个消息“prepare”、 “vote-commit”、 “global-commit”、 “确认 global-commit”。过多的交互次数会降低性能。另一方面,协调者需要等待所有的参与者的投票结果,一旦存在较慢的参与者,会影响全局流程执行速度。

虽然存在一些改进的两阶段提交协议可以提高容错能力和性能,然而这类协议依旧是在工程中使用较少的一类协议,其理论价值大于实践意义。

参考:《分布式系统原理介绍》 - 刘杰

分布式系统原理 之6 两阶段提交协议相关推荐

  1. 分布式系统中的一致性协议之两阶段提交协议(2PC)

    分布式系统中的一致性协议之两阶段提交协议(2PC) 两阶段提交协议是很常见的解决分布式事务的方式,他可以保证分布式事务中,要么所有参与的进程都提交事务成功,要么都取消事务,这样做可以在分布式环境中保持 ...

  2. 分布式系统中的两阶段提交协议

    分布式系统中的两阶段提交协议 在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败.当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为 ...

  3. Flink——Flink CheckPoint之两阶段提交协议(Two-Phase Commit Protocol)

    文章目录 两阶段提交协议 1. 两阶段提交的前提条件 2. 两阶段提交的基本算法 a. 第一阶段(提交请求阶段) b. 第二阶段(提交执行阶段) 3. 两阶段提交的缺点 Flink-两阶段提交协议 1 ...

  4. 分布式系统理论之两阶段提交协议

    一,两阶段提交协议介绍 两阶段提交协议是用来保证分布式系统事务的协议.在分布式系统中,一个事务需要由多台机器协调完成,机器之间通过网络来通信,如何保证一组操作在多台机器上要么都做,要么都不做呢?(事务 ...

  5. 关于分布式事务、两阶段提交协议、三阶提交协议

    随着大型网站的各种高并发访问.海量数据处理等场景越来越多,如何实现网站的高可用.易伸缩.可扩展.安全等目标就显得越来越重要.为了解决这样一系列问题,大型网站的架构也在不断发展.提高大型网站的高可用架构 ...

  6. 两阶段提交协议(two phase commit protocol,2PC)详解

    一.协议概述 两阶段提交协议(two phase commit protocol,2PC)可以保证数据的强一致性,许多分布式关系型数据管理系统采用此协议来完成分布式事务.它是协调所有分布式原子事务参与 ...

  7. 【其他】2PC两阶段提交协议

    2PC两阶段提交协议 参考文章:https://blog.csdn.net/xj15010735572/article/details/86233456 背景: 在项目中开启了分布式事务,底层代码通过 ...

  8. 两阶段提交协议的异常处理

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt371 两阶段提交的协议大家都比较熟悉了,解释一下每个阶段的异常处理.首先,我 ...

  9. 关于分布式事务、2pc两阶段提交协议、3pc三阶提交协议

    本文转载自:https://mp.weixin.qq.com/s/87-znh7Q-SvQfF9u8O3Trg 随着大型网站的各种高并发访问.海量数据处理等场景越来越多,如何实现网站的高可用.易伸缩. ...

最新文章

  1. Strategy_Level2
  2. 图灵访谈:柳泽大辅谈如何想出好创意
  3. Monkey基本用法与常用参数
  4. 第二章 Vue快速入门-- 28 自定义按键修饰符
  5. CABasicAnimation动画
  6. Android性能优化 ---(6)自启动管理
  7. 数据库级联操作mysql_Oracle数据库中的级联查询、级联删除、级联更新操作教程...
  8. (四)Qt实现自定义模型基于QAbstractTableModel
  9. 【数据分析】Superset 之三 Docker操作管理
  10. Charles(网络封包分析工具)
  11. 004-Python内置数据结构-七种数据结构一览
  12. 算法设计与分析基础 (Anany Levitin 著)
  13. STM32 ADC 过采样技术
  14. 飞Young任意路由器连接[破解路由器限制]
  15. 手机浏览器打开微信小程序,支持外部浏览器跳转到小程序
  16. chrome 打印布局_Chrome打印网页中的宽度控制
  17. java word转pdf在linux系统上可行
  18. 在word中写出打勾的方框
  19. ICCV2021 Oral 论文及论文实现代码合集
  20. Relief特征选择算法

热门文章

  1. 数据科学竞赛-计算机视觉赛流程
  2. 贪心算法-02活动安排问题
  3. js src 变量_Js基础学习笔记(一)
  4. vc中ASSERT()和VERIFY()区别
  5. MySQL中B-tree索引和Hash索引区别
  6. 手把手教你拦截Linux系统调用
  7. 从零开始玩转JMX(三)——Model MBean
  8. MySQL的内连和外连
  9. 【城市沙龙】LiveVideoStack Meet|西安:人文历史遇到流媒体算法
  10. LiveVideoStack主编观察02 / 附赠专属优惠码