2. 分布式事务基础:ACID与CAP理论、BASE理论、两阶段提交(2PC)与三阶段提交(3PC)原理
在微服务与分布式架构中,事务不再局限于单一数据库的本地边界。当一次业务操作需要跨多个服务、多个数据源保持一致性时,传统的本地事务机制便失效了。本章将系统梳理分布式事务的核心理论基础,包括ACID与CAP的冲突、BASE的妥协策略,以及经典的2PC与3PC协调协议。
2.1 本地事务的ACID原则
在讨论分布式事务之前,必须回顾单机数据库事务的四大特性,它们是所有事务一致性的参照基准。
| 特性 | 全称 | 核心含义 | 典型违反场景 |
|---|---|---|---|
| 原子性 | Atomicity | 事务中的所有操作要么全部成功,要么全部回滚,不存在中间状态。 | 转账扣款成功但加款失败,资金丢失。 |
| 一致性 | Consistency | 事务执行前后,数据库的完整性约束(主键、外键、业务规则)不被破坏。 | 订单总金额与明细金额之和不相等。 |
| 隔离性 | Isolation | 并发执行的事务之间互不干扰,每个事务都感觉自己是唯一运行的。 | 脏读、不可重复读、幻读。 |
| 持久性 | Durability | 一旦事务提交,其结果就是永久性的,即使系统崩溃也不会丢失。 | 提交后断电,数据未写入磁盘。 |
关键认知: 在分布式系统中,一致性(C) 的含义发生了迁移。ACID中的C是数据库内部约束一致性;而分布式事务讨论的C是多副本/多节点数据状态的一致性,即所有节点在同一时刻看到的数据是否相同。
2.2 CAP理论:分布式系统的“不可能三角”
2000年,Eric Brewer教授提出了CAP定理,指出分布式数据系统最多只能同时满足以下三个特性中的两个:
- C(Consistency,强一致性): 所有节点在同一时刻看到的数据完全相同。对任何节点的读操作都能返回最新的写入结果。
- A(Availability,可用性): 每个请求都能获得一个(非错误的)响应,但不保证响应包含最新数据。
- P(Partition Tolerance,分区容错性): 系统中任意节点间的网络通信中断(即发生网络分区),系统仍能继续运行。
由于网络分区在分布式环境中是必然发生的,因此P是必须选择的。实际架构决策变成了在CP(强一致+分区容忍) 与AP(高可用+分区容忍) 之间做权衡。
架构启示: 在微服务鉴权拦截场景中,如果使用分布式事务,通常优先保证 AP(用户请求不阻塞),通过最终一致性补偿来达到数据一致。例如,先放行请求,再通过异步消息队列同步鉴权结果。
2.3 BASE理论:AP系统的实践指南
BASE理论是对CAP中AP模式的一种延伸,它放弃了强一致性,转而追求最终一致性。BASE是以下三个概念的缩写:
- BA(Basically Available,基本可用): 系统允许出现部分功能降级,但核心功能仍然可用。例如,双十一期间,订单查询服务可以降级为只返回最近3个月的订单。
- S(Soft State,软状态): 允许系统中的数据存在中间状态,且该状态不影响系统整体可用性。例如,订单状态为“支付中”,而不是立即变为“已支付”。
- E(Eventually Consistent,最终一致性): 经过一段时间的数据同步后,所有副本最终会达到一致状态。例如,转账后,A账户扣款立即生效,B账户加款可能在几秒后到账。
| 对比维度 | ACID | BASE |
|---|---|---|
| 一致性模型 | 强一致性,事务提交后立即全局可见 | 最终一致性,允许短暂不一致 |
| 可用性优先级 | 低,事务冲突时可能阻塞或回滚 | 高,优先保证请求被处理 |
| 适用场景 | 金融交易、库存扣减(强一致要求) | 社交动态、用户鉴权、日志记录 |
| 实现复杂度 | 较低(依赖数据库锁与日志) | 较高(需要补偿、重试、对账机制) |
2.4 两阶段提交(2PC):经典的强一致协议
2PC是分布式事务中最经典的强一致性实现方案,由一个协调者(Coordinator) 和多个参与者(Participant) 组成,分为两个阶段:
阶段一:投票阶段(Voting Phase)
- 协调者向所有参与者发送
prepare请求,询问是否可以提交事务。 - 参与者执行本地事务(写redo/undo日志),但不提交,将状态锁定。
- 参与者回复
Yes(准备就绪)或No(失败/中止)。
阶段二:提交/中止阶段(Commit/Abort Phase)
- 如果协调者收到所有参与者的
Yes,则广播commit指令;否则广播abort指令。 - 参与者收到指令后,执行提交或回滚,并释放资源锁。
- 参与者向协调者确认操作完成。
2PC 的致命缺陷:
- 同步阻塞: 参与者在投票后必须等待协调者的最终指令,期间锁定资源,性能低下。
- 单点故障: 协调者崩溃会导致所有参与者无法释放锁,甚至出现数据不一致。
- 脑裂风险: 协调者在发送 commit 前宕机,部分参与者可能已经提交,部分未提交,无法统一。
2.5 三阶段提交(3PC):引入超时与预提交
3PC是2PC的改进版本,主要目的是解决2PC的阻塞问题。它将投票阶段拆分为CanCommit 和 PreCommit 两个阶段,并引入了超时机制。
3PC的三个阶段
| 阶段 | 动作 | 说明 |
|---|---|---|
| 1. CanCommit | 协调者询问参与者是否可以执行事务 | 参与者只检查自身状态(如资源是否充足),不执行任何事务操作,不锁定资源。回复 Yes/No。 |
| 2. PreCommit | 协调者发送预提交指令 | 参与者收到后,执行本地事务(写日志),但不提交。此时如果参与者超时未收到后续指令,会自动中止(避免2PC的永久阻塞)。 |
| 3. DoCommit | 协调者发送最终提交指令 | 参与者收到后正式提交事务。如果参与者超时未收到指令,会继续提交(因为预提交阶段已经确认可以提交,超时后默认提交)。 |
3PC 与 2PC 的核心区别:
- 超时机制: 参与者在 PreCommit 和 DoCommit 阶段都有超时处理,不会无限等待协调者。
- 预提交阶段: 增加了 PreCommit 作为缓冲,让参与者提前执行事务,减少最终提交时的失败概率。
- 缺点: 3PC 仍然无法完全解决数据不一致问题。如果在 PreCommit 后协调者崩溃,且部分参与者超时提交、部分超时中止,仍然会出现数据不一致。
2.6 分布式事务选型对照
在实际的微服务鉴权拦截单元测试中,选择哪种分布式事务方案取决于业务对一致性和性能的要求。下表总结了本章涉及的三种核心理论/协议的适用场景:
| 方案 | 一致性级别 | 性能 | 典型应用场景 | 测试关注点 |
|---|---|---|---|---|
| 2PC | 强一致性 | 低(同步阻塞) | 金融核心账务、跨库转账 | 协调者故障、参与者超时、锁超时 |
| 3PC | 强一致性(有改善) | 中(引入超时) | 对可用性要求稍高的强一致场景 | 网络分区、超时阈值、默认提交逻辑 |
| BASE/TCC | 最终一致性 | 高(异步补偿) | 用户鉴权、订单状态、积分系统 | 补偿幂等性、空回滚、悬挂事务 |
| 本地消息表 | 最终一致性 | 高(异步) | 跨服务状态同步、日志记录 | 消息重试、去重、死信处理 |
课程关联: 在后续的《基于Development环境的分布式事务鉴权拦截单元测试》实战章节中,我们将重点使用 TCC(Try-Confirm-Cancel) 模式(BASE理论的典型实现)来模拟鉴权服务的分布式事务场景。理解2PC/3PC的阻塞与超时机制,将帮助你更好地设计TCC的补偿逻辑与单元测试用例。