Saga模式通过将长事务拆分为多个本地事务并配以补偿操作,实现无锁、异步、最终一致的柔性事务;其核心优势在于释放资源锁、避免阻塞、适配支付等待、物流延迟等真实业务节奏。

直接用 Saga 替代 2PC,核心不是“换一个框架”,而是把长事务从“锁资源等结果”变成“分步提交+出错回滚”。重点在于释放锁、避免阻塞、适配真实业务节奏——比如用户下单后要等支付、物流要等运输、结算要等确认收货,这些天然不能强同步,硬套 2PC 只会让系统卡死。
为什么 2PC 在长事务里会拖垮性能
2PC 要求所有参与者在 Prepare 阶段就执行操作、预留资源、锁住数据,直到协调者发 Commit 或 Rollback 才释放。而长事务中: - 支付可能等用户扫码 5 分钟 - 物流状态更新可能隔几小时才回调 - 外部服务(如银行、快递)响应不可控、超时频繁 这时锁会长时间持有,数据库连接池耗尽、线程阻塞、TPS 断崖下跌。实测中,Prepare 阶段平均锁持有时间 400ms+,而业务逻辑本身仅 12ms,90% 时间都在等。
Saga 是怎么做到无锁、高性能的
Saga 把整个流程拆成多个本地事务(LT),每个 LT 独立提交、立刻释放锁、不依赖其他步骤结果:
- 每一步只管自己:下单 → 立即提交订单表;扣库存 → 立即更新库存字段;发支付单 → 立即写支付流水;全部各自 commit,不互相等待
- 补偿操作是反向更新:比如“扣库存”的补偿是“加回库存”,不是回滚事务,而是执行一条新 SQL(UPDATE stock SET qty = qty + 10 WHERE id = ?)
- 幂等是底线:每个 LT 和补偿操作都必须支持重复执行(加唯一索引、用状态机判断当前是否已执行过)
- 状态驱动推进:用状态字段(如 order_status = 'paid')作为下一步触发条件,而不是靠协调者轮询或超时唤醒
两种落地方式选哪个更稳
Java 项目推荐优先用协调式(Orchestration),尤其流程超过 4 步或含外部调用时:
- 引入 Saga Manager(可用 Spring State Machine、自研轻量协调器或 Seata Saga 模式)统一维护执行序列和失败路径
- 每步成功后,由协调器发指令给下一步服务(同步 HTTP 或异步消息),失败时自动按逆序调用补偿
- 比编排式(Choreography)更易追踪、调试、补单——日志里能清晰看到“T3 失败 → 触发 C2 → C1”,而编排式靠事件广播,链路分散难定位
- 补偿失败要有兜底:比如 C2 执行失败,记录告警并转入人工干预队列,避免雪崩
关键细节别漏掉
光拆事务不够,这几个点决定 Saga 是否真能跑稳:
立即学习“Java免费学习笔记(深入)”;
- 补偿不是“undo”,而是“cancel”:不是回滚数据库事务,而是执行业务语义明确的反向操作(如“创建优惠券”补偿是“作废优惠券”,不是删记录)
- 状态持久化必须原子:更新业务状态(如将订单设为“已发货”)和发布下一步事件,要在同一个本地事务里完成,防止状态与事件不一致
- 重试要有退避+上限:补偿失败默认重试 3 次,间隔 1s/3s/10s,超限进死信队列,避免反复刷库
- 跨库场景用可靠事件:订单库和库存库不在一起?用本地消息表 + 定时扫描,确保事件至少投递一次,再由下游消费



















