Saga 与分布式事务
编排 vs 协同;补偿事务直觉。
40 分钟
Saga 与分布式事务
跨多个微服务、多个数据库时,没有单机 @Transactional 能罩住全程。Saga 把长事务拆成 本地事务 + 补偿步骤,追求 最终一致 而非 ACID 全局锁。
学习目标
- 对比编排式(Orchestration)与协同式(Choreography)Saga
- 理解补偿事务与「业务层回滚」的区别
- 知道何时消息流比 2PC 更现实
问题场景
创建订单 → 扣库存 → 扣积分 → 发通知
│ │ │
order_db inventory_db points_db (三个独立数据源)
任一环节失败,前面已提交的步骤需要 可逆操作(释放库存、作废订单),不能靠数据库 rollback。
编排式 Saga(Orchestrator)
┌─────────────────┐
│ Order Saga │
│ Orchestrator │
└────────┬────────┘
┌───────────────────┼───────────────────┐
▼ ▼ ▼
reserveInventory deductPoints sendNotify
│ │ │
失败 ◄───────────────────┴── 触发 compensateRelease...
中心状态机(常独立服务或 order-svc 内模块)显式 发命令、收结果、决定下一步/补偿。调试路径清晰,适合步骤多、规则复杂。
协同式 Saga(Choreography)
order-svc ──OrderCreated──► Kafka ──► inventory-svc 扣库存
│
InventoryFailed ◄────┘
│
order-svc ◄── 订阅失败事件 ── 执行 CancelOrder
无中心指挥,靠 领域事件链 推进(ip-event-driven)。耦合低,但全局状态难一眼看清。
编排 vs 协同
| 维度 | Orchestration | Choreography |
|---|---|---|
| 可见性 | 状态机集中 | 事件 scattered |
| 耦合 | Orchestrator 知各步 API | 服务只认事件 |
| 实现 | 状态表 + Feign/MQ | Kafka + 消费者 |
rmq-spring 与 kafka-spring 都可承载 Saga 消息;关键是 幂等 + 可补偿。
补偿是 新业务操作(ReleaseInventory),每步 幂等(ip-idempotency),失败走 DLQ。步骤过多时审视边界()。