seata底层源码是如何实现的-saga 篇

SAGA 模式在使用方式上(如通过注解或配置定义事务)可能与 Seata 的 AT、TCC 模式看似相似,但它的设计目标和适用场景与其他模式有本质区别,尤其在「长事务」场景中具有不可替代的优势。以下从「SAGA 与其他模式的核心差异」「长事务的定义」「SAGA 为何适配长事务」三个层面展开说明。

一、SAGA 与其他模式的核心区别(为何专用于长事务)

Seata 的 AT、TCC 模式本质是「短事务」解决方案,而 SAGA 是「长事务」解决方案,核心差异体现在事务持续时间资源锁定方式上:

模式 事务持续时间 资源锁定方式 适用场景 为何不适合长事务
AT 短(毫秒 / 秒级) 全局锁 + 数据库锁(短时间持有) 高频、短流程(如订单支付) 锁持有时间长会导致并发阻塞,性能急剧下降
TCC 短(毫秒 / 秒级) 业务层锁(如冻结资源) 复杂业务逻辑(如跨境支付) 冻结资源长期不释放,导致资源利用率极低
SAGA 长(分钟 / 小时级) 无锁,依赖补偿机制 跨多系统、长流程(如物流调度) 允许资源临时不一致,通过补偿最终一致

关键差异点

  • AT/TCC 依赖「锁机制」保证数据即时一致性,锁必须在短时间内释放(否则阻塞并发),因此只能处理短事务。
  • SAGA 放弃锁机制,允许中间状态存在(如订单创建后未支付、库存临时超卖),通过「补偿操作」最终修复一致性,因此能支撑长时间运行的事务。

二、什么是「长事务」?

长事务指执行时间长(分钟、小时甚至天级)、涉及多个跨系统步骤的事务,典型场景如:

  • 电商的「订单 - 支付 - 发货 - 签收 - 结算」全流程(可能持续数天)。
  • 供应链的「采购申请 - 审批 - 供应商发货 - 入库 - 付款」流程(可能持续数周)。
  • 金融的「贷款申请 - 征信 - 审批 - 签约 - 放款」流程(可能持续数天)。

这类事务的特点:

  1. 步骤多且分散在多个独立系统(如订单系统、物流系统、财务系统)。
  2. 步骤间可能存在人工干预(如审批、签收),导致整体耗时极长。
  3. 无法接受资源长期锁定(如订单未支付时,库存不能被锁几天)。

三、SAGA 模式为何适合长事务?

SAGA 模式通过状态持久化补偿机制无锁设计三大特性,完美适配长事务的需求:

1. 状态持久化:支持断点续跑

长事务可能因服务重启、网络中断等原因中断,SAGA 通过 saga_instance 和 saga_step_instance 表持久化事务状态,重启后可从断点继续执行:

java

运行

// 服务重启后,SAGA 引擎自动恢复未完成的事务
public class SagaRecoveryService {
    @Autowired
    private StateMachineEngine engine;
    @Autowired
    private SagaRepository repository;

    @PostConstruct
    public void recover() {
        // 查询数据库中“运行中”或“失败”的事务实例
        List<StateMachineInstance> instances = repository.findUnfinishedInstances();
        for (StateMachineInstance instance : instances) {
            // 从断点继续执行
            engine.retry(instance.getId());
        }
    }
}
  • 这是长事务的核心需求:即使中断数小时,也能恢复执行,无需从头开始。
2. 补偿机制:允许中间状态,最终一致

长事务中,步骤间可能间隔数小时(如用户下单后几小时才支付),无法通过锁保持资源一致性。SAGA 允许中间状态存在,若最终失败则通过补偿回滚:

  • 例如:订单创建 → 库存预扣 → (2 小时后)支付失败 → 补偿(释放库存)。
  • 补偿逻辑由业务代码定义(如 cancelOrder refundStock),灵活处理各种中间状态。
3. 无锁设计:不阻塞并发,适合长时间运行

SAGA 不依赖全局锁或资源锁定,允许其他事务并发操作资源(如多个订单同时预扣同一商品库存),仅通过业务逻辑(如库存校验)和补偿机制处理冲突:

  • 例如:两个订单同时预扣库存导致超卖,SAGA 会在支付阶段校验实际库存,失败的订单触发补偿释放库存。
  • 这种设计避免了 AT/TCC 中 “锁长期持有导致的并发阻塞”,适合长事务的低阻塞需求。

四、长事务使用 SAGA 的好处

  1. 支持跨系统长流程长事务往往涉及多个独立系统(如订单、物流、财务),SAGA 通过状态机定义跨系统步骤,无需硬编码流程逻辑,适配复杂的跨系统协作。

  2. 容忍中间状态和人工干预长事务中常有人工操作(如审批、确认),SAGA 允许事务暂停等待人工操作,后续通过回调或定时任务继续执行,其他模式无法支持这种 “断点等待”。

  3. 低侵入性和高灵活性SAGA 通过配置文件(JSON/YAML)定义流程,新增步骤或修改补偿逻辑无需修改业务代码,适合长事务的需求迭代(如物流流程新增 “质检” 步骤)。

  4. 高容错性长事务执行时间长,发生故障的概率更高。SAGA 通过状态持久化和重试机制,确保故障后能恢复执行;通过补偿机制,确保最终数据一致。

结论

SAGA 模式看似与其他模式使用方式相似,但其无锁设计状态持久化补偿机制使其专为长事务设计:

  • 长事务的核心需求是「允许长时间运行、支持断点续跑、容忍中间状态」,这些都是 AT/TCC 等短事务模式无法满足的。
  • SAGA 放弃了即时一致性,通过最终一致性适配长事务场景,在跨系统、多步骤、长时间的业务中不可替代。

源码分析

Seata 的 SAGA 模式专为 长事务场景 设计(如跨多个微服务的订单流程、物流调度等),核心通过 状态机驱动 和 补偿机制 实现柔性事务,支持复杂流程编排和失败补偿。以下从源码层面解析其底层实现逻辑(基于 Seata 1.6.x 版本)。

一、SAGA 模式核心原理与角色

SAGA 模式的核心是将长事务拆分为多个 本地事务步骤,每个步骤对应一个 正向操作 和一个 补偿操作(用于失败时回滚)。Seata 中 SAGA 模式的核心角色:

  • StateMachineEngine:状态机引擎,负责解析状态机定义、驱动流程执行、管理事务状态。
  • SagaCoordinator:协调器,负责记录事务执行状态、触发补偿操作。
  • SagaRepository:事务状态仓库,持久化事务实例和步骤状态(支持数据库、文件等存储)。

核心流程

  1. 正常执行:按状态机定义的顺序执行正向操作,记录每个步骤的执行状态。
  2. 失败补偿:若某步骤执行失败,按 逆序 执行已完成步骤的补偿操作,最终达到事务一致性。

二、源码解析:SAGA 状态机定义与初始化

SAGA 模式通过 JSON/YAML 配置文件 定义事务流程(步骤、正向 / 补偿方法、依赖关系等),状态机引擎在启动时解析配置并初始化。

1. 状态机配置示例(JSON)

json

{
  "name": "orderSaga",
  "comment": "订单创建-支付-发货的长事务流程",
  "startState": "createOrder",
  "states": [
    {
      "name": "createOrder",
      "type": "ServiceTask",
      "action": {
        "serviceName": "orderService",
        "methodName": "createOrder",
        "compensateMethod": "cancelOrder" // 补偿方法
      },
      "transition": "pay" // 下一步骤
    },
    {
      "name": "pay",
      "type": "ServiceTask",
      "action": {
        "serviceName": "paymentService",
        "methodName": "pay",
        "compensateMethod": "refund"
      },
      "transition": "deliver"
    },
    {
      "name": "deliver",
      "type": "ServiceTask",
      "action": {
        "serviceName": "deliveryService",
        "methodName": "deliver",
        "compensateMethod": "cancelDelivery"
      },
      "end": true // 流程终点
    }
  ]
}
2. 状态机解析与引擎初始化

状态机引擎(StateMachineEngine)启动时加载配置文件,解析为可执行的状态机实例:

关键代码:StateMachineConfigParser(配置解析)

java

运行

public class StateMachineConfigParser {
    public StateMachine parse(String configContent) {
        // 1. 解析 JSON 配置为 StateMachine 实体
        StateMachine stateMachine = JSON.parseObject(configContent, StateMachine.class);
        // 2. 初始化每个状态(步骤)的 action 信息(正向/补偿方法)
        for (State state : stateMachine.getStates()) {
            if (state.getType() == StateType.ServiceTask) {
                ServiceTaskState serviceTask = (ServiceTaskState) state;
                Action action = serviceTask.getAction();
                // 反射获取正向方法和补偿方法的元数据(参数、返回值等)
                MethodInvoker invoke = buildMethodInvoker(
                    action.getServiceName(), 
                    action.getMethodName()
                );
                MethodInvoker compensateInvoke = buildMethodInvoker(
                    action.getServiceName(), 
                    action.getCompensateMethod()
                );
                serviceTask.setActionInvoker(invoke);
                serviceTask.setCompensateInvoker(compensateInvoke);
            }
        }
        return stateMachine;
    }

    // 构建方法调用器(通过 Spring 容器获取 bean 并反射方法)
    private MethodInvoker buildMethodInvoker(String serviceName, String methodName) {
        Object serviceBean = SpringContextHolder.getBean(serviceName);
        Method method = findMethod(serviceBean.getClass(), methodName);
        return new ReflectiveMethodInvoker(serviceBean, method);
    }
}

关键代码:StateMachineEngineImpl(引擎初始化)

java

运行

public class StateMachineEngineImpl implements StateMachineEngine {
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值