1. ACID 原理与单体场景的数据一致性
在关系型数据库领域,ACID 是衡量事务可靠性的基石。原子性确保一个事务要么全部成功,要么全部回滚;一致性确保事务提交前后数据库状态保持正确;隔离性避免并发操作互相干扰;持久性保证提交后的数据即使发生故障也不会丢失。
在单机或单数据库内,使用自带的事务管理即可实现强一致性。通过设置合适的隔离级别(如可重复读、串行化),可以降低脏读、不可重复读等并发问题,同时也需要权衡性能与并发能力。
然而,当业务跨越多个数据库、服务甚至数据中心时,全局原子性难以由单一数据库事务保证,这就引出对分布式事务的一系列设计与实践问题。

2. 分布式事务的挑战与核心模型
1) 两阶段提交(2PC)及其工作原理
2PC 将全局事务分解为“准备阶段”和“提交阶段”。在准备阶段,各参与方执行本地事务并锁定资源,向协调者返回准备就绪的应答;在提交阶段,协调者统一发出提交指令,参与方真正完成提交或在异常时进行回滚。
该模型的关键在于协调者与参与方的交互,以及故障时的阻塞问题。若协调者崩溃或网络分区,参与方可能一直处于等待状态,导致系统整体不可用甚至出现资源长时间锁定。
2PC 在强一致性场景下具备理论可实现性,但现实中的分布式系统往往需要更高的可用性与容错能力,因此催生了更灵活的模型与组合方案。
2) Saga 与 TCC 的实战路线
Saga 提供了一种通过顺序执行一组本地事务,并在失败时触发补偿事务的方式来实现最终一致性。它不要求全局原子性,而是通过补偿机制确保业务层面的正确性。
TCC(Try-Confirm-Cancel)模型则将事务分为Try、Confirm、Cancel三阶段,前置操作与提交/回滚分离,通过幂等性设计确保高并发场景中的正确性与可用性。
这两种方案都强调对业务语义的保护与补偿逻辑的显式化,适合微服务架构、跨数据库场景中的数据一致性需求。
3. 工程实践:幂等性、补偿与事件溯源
1) 幂等性设计与幂等键
在分布式事务中,幂等性是避免重复执行造成错误的重要机制。通过为每个操作定义幂等键(如唯一请求ID),可以在重试、重放时确保仅产生一次效果。
实现要点包括对幂等键的存储与查询、对幂等键的全局可用性,以及对并发重复请求的顺序控制。对于幂等性良好的接口,重试策略可以显著提升系统健壮性。
此外,设计时还要考虑幂等键的分布式一致性与防撞策略,以避免不同服务之间产生键冲突。
2) 事件溯源与补偿机制
事件溯源将系统状态变更抽象为事件流,通过事件日志驱动状态重建与回放。事件驱动架构有利于实现可观测性、问题追踪,以及为补偿提供清晰线索。
当某一步发生异常时,可以通过触发补偿事件来回滚影响,从而维护外部系统的一致性。该方法通常需要设计明确的事件命名、版本控制、幂等处理策略。
在实际系统中,事件溯源还需要考虑日志存储容量、归档策略以及跨服务的事件顺序一致性问题。
4. 实战代码示例:Saga 流程与实现要点
1) Saga 编排器的伪代码
下面给出一个简化的 Saga 编排器示例,用来演示如何顺序执行多个本地事务并在失败时触发补偿。
核心思想:通过一个执行记录列表追踪已执行的步骤,根据异常情况逐步执行补偿。
class SagaStep:def __init__(self, action, compensation, name="step"):self.action = actionself.compensation = compensationself.name = namedef run_saga(steps):executed = []for s in steps:try:s.action()executed.append(s)except Exception as e:# 回滚已执行的步骤for s in reversed(executed):s.compensation()raise# 示例:定义三个本地事务及补偿
def a(): print("做A")
def a_comp(): print("回滚A")def b(): print("做B")
def b_comp(): print("回滚B")def c(): print("做C")
def c_comp(): print("回滚C")steps = [SagaStep(a, a_comp, "A"),SagaStep(b, b_comp, "B"),SagaStep(c, c_comp, "C"),
]run_saga(steps)
在真实环境中,每一步的本地事务需要是原子且可回滚的,并且补偿逻辑应对外部依赖性与幂等性进行严格设计。
2) Saga 的事件驱动扩展示例
若采用事件驱动的 Saga,系统会将每一步的成功作为事件发布,后续步骤订阅并执行。若某一步失败,补偿事件 将触发前面的步骤回滚。
// JavaScript 伪代码:事件驱动 Saga
async function step1(){ /* 调用微服务1 */ }
async function compensate1(){ /* 补偿步骤1 */ }async function step2(){ /* 调用微服务2 */ }
async function compensate2(){ /* 补偿步骤2 */ }async function runSagaOrchestrator(steps){for (let s of steps){await s.action()}
}
// 实际中,还会有事件总线与状态机来管理状态转移


