亿级流量架构之分布式事务思路及方法( 五 )


三阶段提交协议三阶段提交协议(3PC:Three-Phase Commit), 针对两阶段提交存在的问题 , 三阶段提交协议通过引入一个 预询盘 阶段 , 以及超时策略来减少整个集群的阻塞时间 , 提升系统性能 。三阶段提交的三个阶段分别为:预询盘(can_commit)、预提交(pre_commit) , 以及事务提交(do_commit) 。

亿级流量架构之分布式事务思路及方法

文章插图
 
第一阶段:预询盘该阶段协调者会去询问各个参与者是否能够正常执行事务 , 参与者根据自身情况回复一个预估值 , 相对于真正的执行事务 , 这个过程是轻量的 , 具体步骤如下:
  1. 协调者向各个参与者发送事务询问通知 , 询问是否可以执行事务操作 , 并等待回复;
  2. 各个参与者依据自身状况回复一个预估值 , 如果预估自己能够正常执行事务就返回确定信息 , 并进入预备状态 , 否则返回否定信息 。
第二阶段:预提交本阶段协调者会根据第一阶段的询盘结果采取相应操作 , 询盘结果主要有 3 种:
  1. 所有的参与者都返回确定信息 。
  2. 一个或多个参与者返回否定信息 。
  3. 协调者等待超时 。
针对第 1 种情况 , 协调者会向所有参与者发送事务执行请求 , 具体步骤如下:
  1. 协调者向所有的事务参与者发送事务执行通知;
  2. 参与者收到通知后执行事务但不提交;
  3. 参与者将事务执行情况返回给客户端 。
在上述步骤中 , 如果参与者等待超时 , 则会中断事务 。针对第 2 和第 3 种情况 , 协调者认为事务无法正常执行 , 于是向各个参与者发出 abort 通知 , 请求退出预备状态 , 具体步骤如下:
  1. 协调者向所有事务参与者发送 abort 通知;
  2. 参与者收到通知后中断事务 。

亿级流量架构之分布式事务思路及方法

文章插图
 
第三阶段:事务提交如果第二阶段事务未中断 , 那么本阶段协调者将会依据事务执行返回的结果来决定提交或回滚事务 , 分为 3 种情况:
  1. 所有的参与者都能正常执行事务 。
  2. 一个或多个参与者执行事务失败 。
  3. 协调者等待超时 。
针对第 1 种情况 , 协调者向各个参与者发起事务提交请求 , 具体步骤如下:
  1. 协调者向所有参与者发送事务 commit 通知;
  2. 所有参与者在收到通知之后执行 commit 操作 , 并释放占有的资源;
  3. 参与者向协调者反馈事务提交结果 。

亿级流量架构之分布式事务思路及方法

文章插图
 
针对第 2 和第 3 种情况 , 协调者认为事务无法成功执行 , 于是向各个参与者发送事务回滚请求 , 具体步骤如下:
  1. 协调者向所有参与者发送事务 rollback 通知;
  2. 所有参与者在收到通知之后执行 rollback 操作 , 并释放占有的资源;
  3. 参与者向协调者反馈事务回滚结果 。

亿级流量架构之分布式事务思路及方法

文章插图
 
在本阶段如果因为协调者或网络问题 , 导致参与者迟迟不能收到来自协调者的 commit 或 rollback 请求 , 那么参与者将不会如两阶段提交中那样陷入阻塞 , 而是等待超时后继续 commit , 相对于两阶段提交虽然降低了同步阻塞 , 但仍然无法完全避免数据的不一致 。两阶段提交协议中所存在的长时间阻塞状态发生的几率还是非常低的 , 所以虽然三阶段提交协议相对于两阶段提交协议对于数据强一致性更有保障 , 但是因为效率问题 , 两阶段提交协议在实际系统中反而更加受宠 。
TCC模式TCC是Try、Confirm 和 Cancel三个单词首字母缩写,它们分别的职责是:
Try:负责预留资源(比如新建一条状态=PENDING的订单);
做业务检查 , 简单来说就是不能预留已经被占用的资源;
隔离预留资源 。
Confirm:负责落地所预留的资源
真正的执行业务使用try阶段预留的资源,幂等 。
Cancel: 负责撤销所预留的资源
需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作;事务发起方在一阶段执行 Try 方式 , 在二阶段提交执行 Confirm 方法 , 二阶段回滚执行 Cancel 方法 。


推荐阅读