# Transcation

分布式事务的实现算法有很多，有基于 XA 协议的 2PC、3PC，也有业务的分布式事务实现 TCC，还有基于消息的分布式事务。

**分布式事务**是多个单机事务的组合。

## 2PC

二阶段提交（The two-phase commit protocol, 2PC）是 XA 协议的实现方式之一，强一致性。有两个角色，**事务管理器**和**本地资源管理器**。

事务管理器为协调者，负责各个本地资源管理器的提交和回滚。

2PC 有投票（voting）和提交（commit）两个阶段。

1. 事务管理器（协调者）向本地资源管理器（参与者）发送 CanCommit 请求。
2. 参与者执行事务操作，记录日志但不提交。根据执行成功与否，返回 Yes 或 No 消息。
3. 协调者根据 Yes 还是 No 发送 DoCommit 或 DoAbort 请求。
4. 参与者根据 DoCommit 还是 DoAbort 进行事务的提交或回滚，并返回 HaveCommitted 消息。
5. 协调者接受到 HaveCommitted 消息，表示事务结束。

缺点：

* 同步阻塞问题：本地资源管理器占有临界资源时，其它资源管理器若要访问同一资源，则会处于阻塞状态。
* 单点故障问题：一单事务管理发生故障，则整个系统不可用。尤其在提交阶段，资源管理器一直锁定事务资源。
* 数据不一致问题：若提交阶段由于网络异常，仅部分资源管理器收到 DoCommit 请求，则整个系统数据不一致。

## 3PC

三阶段提交协议（Three-phase commit protocol, 3PC）也是 XA 协议的实现方式，强一致性。对 2PC 做了改进，引入了超时机制和准备阶段。

* 参与者与协调者都有超时机制，超时后，根据当前状态选择提交或终止整个事务。
* CanCommit、PreCommit、DoCommit 三个阶段。

1. 协调者发送 CanCommit 请求。
2. 参与者根据状态发送 Yes 或 No。
3. 协调者若收到 No，则发送Abort。若收到全部是 Yes，则发送 PreCommit 请求。
4. 参与者若收到 Abort 或超时后未收到消息，则执行事务中断。若收到 PreCommit 请求，则执行事务操作，并记录 Undo 和 Redo 日志，并相应 ACK。
5. 协调者若收到 ACK，则发送 DoCommit 请求。

很少被使用，因为相比于 2PC 需要更多的消息协商，增加系统负载和响应延时。

## TCC

Try-Confirm-Cancel，最终一致。针对每个操作都要注册一个与其对应的确认操作和撤销操作。确认操作和撤销操作必须是幂等的。是一个业务层面的协议，不依赖于数据库的事务，3 个操作都需要在业务代码中实现。

优点：

* 不依赖数据库事务。

缺点：

* 实现复杂

## 基于消息

最终一致。2PC 和 3PC 都需要锁定资源，通过消息可以解决此问题。
