文章目录
-
- 背景:为什么需要分布式事务
- [两阶段提交协议(2PC, Two-Phase Commit)](#两阶段提交协议(2PC, Two-Phase Commit))
-
- [1️⃣ 核心思想](#1️⃣ 核心思想)
- [2️⃣ 流程](#2️⃣ 流程)
-
- [阶段 1:准备阶段(Prepare Phase)](#阶段 1:准备阶段(Prepare Phase))
- [阶段 2:提交阶段(Commit Phase)](#阶段 2:提交阶段(Commit Phase))
- [3️⃣ 优缺点](#3️⃣ 优缺点)
- [三阶段提交(3PC, Three-Phase Commit)](#三阶段提交(3PC, Three-Phase Commit))
-
- [1️⃣ 核心思想](#1️⃣ 核心思想)
- [2️⃣ 流程](#2️⃣ 流程)
-
- [阶段 1:CanCommit / 询问阶段](#阶段 1:CanCommit / 询问阶段)
- [阶段 2:PreCommit / 预提交阶段](#阶段 2:PreCommit / 预提交阶段)
- [阶段 3:Commit / 提交阶段](#阶段 3:Commit / 提交阶段)
- [3️⃣ 优缺点](#3️⃣ 优缺点)
- [3PC 协调者挂掉](#3PC 协调者挂掉)
- XA事务模式
- TCC事务模式(补偿性事务)
- SAGA事务模式
背景:为什么需要分布式事务
在分布式系统中,一个事务可能涉及多个数据库或服务节点,问题在于:
- 各节点独立提交或回滚,操作不一致 → 数据不一致。
- 需要协调机制保证 原子性(A)。
于是出现了 分布式事务协议:
- 两阶段提交(2PC)
- 三阶段提交(3PC)
两阶段提交协议(2PC, Two-Phase Commit)
1️⃣ 核心思想
将事务提交分为两个阶段:准备阶段(Prepare) + 提交阶段(Commit)
协调者负责决定各参与者最终是提交还是回滚。
是一种 分布式事务协议,核心是 协调者 + 参与者 + 两阶段提交(Prepare + Commit/Rollback)
2️⃣ 流程
阶段 1:准备阶段(Prepare Phase)
-
协调者(Coordinator)通知所有参与者(Participant):
"事务准备提交,请锁资源、写日志、准备提交" -
每个参与者:
-
锁定数据
-
写本地 准备提交日志(prepare log)
-
回复协调者:
Yes / No- Yes → 可以提交
- No → 不可提交,需回滚
-
阶段 2:提交阶段(Commit Phase)
-
协调者根据所有回复:
- 所有 Yes → 发 Commit
- 有 No → 发 Rollback
-
参与者收到命令后:
- 执行提交或回滚
- 释放锁
3️⃣ 优缺点
| 优点 | 缺点 |
|---|---|
| 简单、易实现 | 阻塞型协议:如果协调者挂掉,参与者会一直锁资源 → 阻塞 |
| 保证一致性 | 无法自动处理协调者或网络故障 → 可能需要人工干预 |
三阶段提交(3PC, Three-Phase Commit)
1️⃣ 核心思想
在 2PC 基础上,引入 预提交阶段(Pre-Commit) ,使协议 非阻塞,即协调者挂掉也能避免永久锁定资源。
2️⃣ 流程
阶段 1:CanCommit / 询问阶段
-
协调者问参与者:
"你能提交吗?" -
参与者回复:Yes / No
-
目的:探测各方是否可以提交
阶段 2:PreCommit / 预提交阶段
-
如果所有参与者答 Yes,协调者发 预提交命令
-
参与者:
- 锁资源,写 预提交日志
- 回复协调者"已预提交"
阶段 3:Commit / 提交阶段
-
协调者收到所有参与者确认后:
- 发最终 Commit
-
参与者提交事务并释放锁
3️⃣ 优缺点
| 优点 | 缺点 |
|---|---|
| 相比 2PC 更安全:协调者挂掉时,参与者可通过预提交状态判断是否提交 | 实现复杂度高 |
| 减少阻塞时间 | 需要额外日志与状态管理 |
3PC 协调者挂掉
| 协调者挂掉阶段 | 参与者处理方式 | 阻塞风险 |
|---|---|---|
| CanCommit | 回滚事务 | 无阻塞 |
| PreCommit | 根据预提交状态自决:提交或回滚 | 理论上无阻塞(非阻塞) |
| Commit | 正常提交 | 无阻塞 |
核心优势:预提交阶段让参与者"知道下一步该做什么",即使协调者挂掉,也能避免长时间锁资源 → 相比 2PC 阻塞问题得到改善
- 2PC:保证原子性,一致性,但存在阻塞问题,协调者单点故障敏感
- 3PC:通过增加预提交阶段,减少阻塞,提高容错性,但复杂度增加
- 实际分布式系统中:2PC + 异步补偿机制(Saga 模式) 更常用,因为 3PC 虽非阻塞,但仍不能解决网络分区问题
XA事务模式
XA是什么
XA是由X/Open组织提出的分布式事务的规范,XA规范主要定义了(全局)事务管理器™和(局部)资源管理器(RM)之间的接口。本地的数据库如mysql在XA中扮演的是RM角色
XA一共分为两阶段:
- 第一阶段(prepare):即所有的参与者RM准备执行事务并锁住需要的资源。参与者ready时,向TM报告已准备就绪。
- 第二阶段 (commit/rollback):当事务管理者™确认所有参与者(RM)都ready后,向所有参与者发送commit命令。
目前主流的数据库基本都支持XA事务,包括mysql、oracle、sqlserver、postgre
sql
XA start '4fPqCNTYeSG' -- 开启一个 xa 事务
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG' -- 此调用之前,连接断开,那么事务会自动回滚
-- 当所有的参与者完成了prepare,就进入第二阶段 提交
xa commit '4fPqCNTYeSG'
我们来完成一个完整的XA,我们先看一个成功的XA时序图:

TCC事务模式(补偿性事务)
什么是TCC,TCC是Try、Confirm、Cancel三个词语的缩写,最早是由 Pat Helland 于 2007
年发表的一篇名为《Life beyond Distributed Transactions:an Apostate's
Opinion》的论文提出。
TCC的三个阶段
TCC分为3个阶段
- Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
- Confirm 阶段:如果所有分支的Try都成功了,则走到Confirm阶段。Confirm真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源
- Cancel 阶段:如果所有分支的Try有一个失败了,则走到Cancel阶段。Cancel释放 Try 阶段预留的业务资源。
如果我们要进行一个类似于银行跨行转账的业务,转出(TransOut)和转入(TransIn)分别在不同的微服务里,一个成功完成的TCC事务典型的时序图如下:

https://dtm.pub/guide/start.html
SAGA事务模式
SAGA最初出现在1987年Hector Garcaa-Molrna & Kenneth
Salem发表的论文SAGAS里。其核心思想是将长事务拆分为多个短事务,由Saga事务协调器协调,如果每个短事务都成功提交完成,那么全局事务就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。
拆分为子事务
例如我们要进行一个类似于银行跨行转账的业务,将A中的30元转给B,根据Saga事务的原理,我们将整个全局事务,切分为以下服务:
- 转出(TransOut)服务,这里转出将会进行操作A-30
- 转出补偿(TransOutCompensate)服务,回滚上面的转出操作,即A+30
- 转入(TransIn)服务,转入将会进行B+30
- 转入补偿(TransInCompensate)服务,回滚上面的转入操作,即B-30
整个SAGA事务的逻辑是:
-
执行转出成功=>执行转入成功=>全局事务完成
-
如果在中间发生错误,例如转入B发生错误,则会调用已执行分支的补偿操作,即:
-
执行转出成功=>执行转入失败=>执行转入补偿成功=>执行转出补偿成功=>全局事务回滚完成
一个成功完成的SAGA事务典型的时序图:
