在微服务架构中,一个业务流程往往跨越多个服务,每个服务都有独立数据库。传统单体事务 ACID 已经无法满足需求,这时 Saga 模式就派上用场了。
本文将结合我们深入讨论的内容,帮助你彻底理解 Saga 模式的本质、落地方式及常见误区。
1. Saga 模式概述
Saga 模式是一种 分布式事务管理模式,核心思想是:
-
将一个长事务拆解为多个小事务(Local Transaction)
-
每个小事务只在单个服务内部完成并保证本地 ACID
-
每个小事务都有对应的 补偿操作,用于回滚失败步骤,保证最终一致性
简单理解:Saga 关心"业务步骤是否成功",而不关心 CRUD 的内部实现。
1.1 Saga 小事务 VS CRUD
很多人容易混淆:
"Saga 小事务是不是微服务内部的增删改查操作?"
答案:不是。
-
CRUD :只是实现手段,例如订单服务里
INSERT order、库存服务里UPDATE stock -
Saga 小事务 :是业务流程中的独立步骤,例如"创建订单""扣减库存""扣款支付"
关键点:
-
小事务可以包含多个 CRUD 或 RPC 调用
-
Saga 只关注:这个步骤成功了没?失败了如何补偿?
📌 比喻:
-
CRUD = 手脚
-
Saga 小事务 = 踢球的动作
-
Saga 只关心"动作完成了没",不关心手指怎么动
2. Saga 小事务如何在微服务中执行
以电商下单流程为例,典型流程:
-
用户验证
-
创建订单
-
扣减库存
-
扣款支付
-
物流下单
每个步骤就是一个 Saga 小事务。
2.1 如何拆分小事务
拆分原则:
-
每个小事务只涉及一个服务
-
每个小事务可以独立提交和补偿
| Saga 小事务 | 属于服务 | 内部可能做的操作 |
|---|---|---|
| 用户验证 | User Service | 查用户是否存在、权限检查 |
| 创建订单 | Order Service | INSERT order、生成订单号 |
| 扣减库存 | Inventory Service | UPDATE stock、校验库存 |
| 支付扣款 | Payment Service | 扣款、写账务记录 |
| 物流下单 | Shipping Service | 创建发货单、调用物流 API |
注意:小事务内部可以有多个 CRUD 或 RPC,但 Saga 只关心"这个步骤是否完成"。
3. 补偿机制详解
分布式事务无法用数据库级 rollback,因此 Saga 用 补偿机制。
3.1 补偿逻辑
-
补偿不是用户手动触发
-
补偿逻辑必须由开发者编写
-
执行顺序通常倒序,保证前面成功的步骤被撤销
举例:
-
扣减库存失败
-
订单服务:取消订单
-
支付服务:返还余额
-
-
物流创建失败
-
支付服务:退款
-
库存服务:回库存
-
订单服务:取消订单
-
3.2 同步 Saga(Orchestrator 模式)
-
Orchestrator = 你自己写的总指挥函数
-
顺序调用每个小事务
-
失败立即触发补偿
示例(Go 伪代码):
func PlaceOrderSaga(userId, productId string) error {
err := userService.ValidateUser(userId)
if err != nil { return err }
err = orderService.CreateOrder(userId, productId)
if err != nil { return err }
err = inventoryService.DecreaseStock(productId)
if err != nil {
orderService.CancelOrder(userId, productId) // 补偿
return err
}
err = paymentService.Debit(userId, productId)
if err != nil {
inventoryService.IncreaseStock(productId)
orderService.CancelOrder(userId, productId)
return err
}
err = shippingService.CreateShipment(userId, productId)
if err != nil {
paymentService.Refund(userId, productId)
inventoryService.IncreaseStock(productId)
orderService.CancelOrder(userId, productId)
return err
}
return nil
}
特点:
-
中央 orchestrator 指挥整个流程
-
失败立刻回滚
-
补偿逻辑集中管理
3.3 异步 Saga(事件驱动 / Choreography 模式)
-
每个事务完成后发事件,下一个事务监听事件执行
-
失败时事务自己发失败事件
-
补偿逻辑由事件处理器处理
流程示意:
OrderCreated → InventoryReserve → Payment → Shipping
|
失败事件
↓
补偿处理器回滚之前事务
关键区别:
| 模式 | 谁发现失败 | 谁执行补偿 |
|---|---|---|
| 同步 | Orchestrator | Orchestrator |
| 异步 | 失败事务自己 | 补偿事件处理器 |
4. 常见误区和实践建议
-
误区:Saga 小事务 = CRUD
- 实际上 Saga 关注"业务步骤是否成功",CRUD 是内部实现
-
Orchestrator 不是框架提供
-
同步模式下,你需要自己写 Orchestrator
-
异步模式下,补偿逻辑放在事件处理器里
-
-
补偿逻辑必须自己写
-
不管同步还是异步
-
同步写在 orchestrator 内
-
异步写在事件处理器里
-
-
拆分小事务时要考虑补偿可行性
- 一个小事务必须可回滚,否则整个 Saga 就不可用
-
同步 vs 异步
-
同步:流程顺序明确、易理解,阻塞调用
-
异步:服务解耦,系统可用性高,但流程复杂
-
5. 总结
-
Saga 小事务 = 业务流程步骤,不是 CRUD
-
Orchestrator = 流程总指挥,由开发者自己实现
-
补偿逻辑由开发者编写,保证失败回滚
-
同步 Saga:Orchestrator 按顺序执行
-
异步 Saga:各服务异步发事件,补偿由事件驱动
-
Saga 适合 跨服务、长流程的分布式事务
Saga 模式的核心价值是:保证分布式系统一致性,同时保持高可用性和可伸缩性。