深入理解微服务下的 Saga 模式——以电商下单为例

在微服务架构中,一个业务流程往往跨越多个服务,每个服务都有独立数据库。传统单体事务 ACID 已经无法满足需求,这时 Saga 模式就派上用场了。

本文将结合我们深入讨论的内容,帮助你彻底理解 Saga 模式的本质、落地方式及常见误区。


1. Saga 模式概述

Saga 模式是一种 分布式事务管理模式,核心思想是:

  1. 将一个长事务拆解为多个小事务(Local Transaction)

  2. 每个小事务只在单个服务内部完成并保证本地 ACID

  3. 每个小事务都有对应的 补偿操作,用于回滚失败步骤,保证最终一致性

简单理解:Saga 关心"业务步骤是否成功",而不关心 CRUD 的内部实现。


1.1 Saga 小事务 VS CRUD

很多人容易混淆:

"Saga 小事务是不是微服务内部的增删改查操作?"

答案:不是。

  • CRUD :只是实现手段,例如订单服务里 INSERT order、库存服务里 UPDATE stock

  • Saga 小事务 :是业务流程中的独立步骤,例如"创建订单""扣减库存""扣款支付"

关键点

  • 小事务可以包含多个 CRUD 或 RPC 调用

  • Saga 只关注:这个步骤成功了没?失败了如何补偿?

📌 比喻:

  • CRUD = 手脚

  • Saga 小事务 = 踢球的动作

  • Saga 只关心"动作完成了没",不关心手指怎么动


2. Saga 小事务如何在微服务中执行

以电商下单流程为例,典型流程:

  1. 用户验证

  2. 创建订单

  3. 扣减库存

  4. 扣款支付

  5. 物流下单

每个步骤就是一个 Saga 小事务


2.1 如何拆分小事务

拆分原则:

  1. 每个小事务只涉及一个服务

  2. 每个小事务可以独立提交和补偿

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. 常见误区和实践建议

  1. 误区:Saga 小事务 = CRUD

    • 实际上 Saga 关注"业务步骤是否成功",CRUD 是内部实现
  2. Orchestrator 不是框架提供

    • 同步模式下,你需要自己写 Orchestrator

    • 异步模式下,补偿逻辑放在事件处理器里

  3. 补偿逻辑必须自己写

    • 不管同步还是异步

    • 同步写在 orchestrator 内

    • 异步写在事件处理器里

  4. 拆分小事务时要考虑补偿可行性

    • 一个小事务必须可回滚,否则整个 Saga 就不可用
  5. 同步 vs 异步

    • 同步:流程顺序明确、易理解,阻塞调用

    • 异步:服务解耦,系统可用性高,但流程复杂


5. 总结

  • Saga 小事务 = 业务流程步骤,不是 CRUD

  • Orchestrator = 流程总指挥,由开发者自己实现

  • 补偿逻辑由开发者编写,保证失败回滚

  • 同步 Saga:Orchestrator 按顺序执行

  • 异步 Saga:各服务异步发事件,补偿由事件驱动

  • Saga 适合 跨服务、长流程的分布式事务

Saga 模式的核心价值是:保证分布式系统一致性,同时保持高可用性和可伸缩性

相关推荐
ray_liang1 小时前
用六边形架构与整洁架构对比是伪命题?
java·架构
AI攻城狮2 小时前
OpenClaw Session 管理完全指南:Context 压缩、重置与持久化
人工智能·云原生·aigc
Java编程爱好者2 小时前
字节二面:被问“大模型知识过时了怎么解?”,我答“微调”,面试官当场黑脸:“听说过 RAG 吗?”
架构
葫芦的运维日志6 小时前
从手动部署到GitOps只需四步
架构
sumuve6 小时前
从100行到1行:我是如何重构IoT设备实时数据通信的?
架构·响应式设计
koddnty7 小时前
c++协程控制流深入剖析
后端·架构
Mintopia7 小时前
Vite 与 Uni-App X 的协作原理:从前端开发到多端运行的桥梁
架构
louiX1 天前
深入理解 Android BLE GATT 回调机制:从“回调地狱”到高可靠 OTA 架构
架构
aircrushin1 天前
轻量化大模型架构演进
人工智能·架构
天蓝色的鱼鱼1 天前
你的项目真的需要SSR吗?还是只是你的简历需要?
前端·架构