Pipeline + Saga 分布式扩展规范

Pipeline + Saga 分布式扩展规范(V1.0)

0. 架构结论先行(必须统一认知)

Pipeline 解决"单服务内的确定性执行顺序"
Saga 解决"跨服务副作用的一致性与补偿"

Pipeline ≠ Saga
Pipeline + Saga = 分布式可逆业务内核


1. 为什么 ERP 必须引入 Saga(而不是分布式事务)

1.1 ERP 的真实约束

  • 跨服务(库存 / 财务 / 结算 / 物流)

  • 高并发

  • 外部系统不可控

  • 允许"最终一致",不允许"状态错乱"

1.2 为什么不用 XA / 2PC

问题 结果
性能
外部系统
云原生
可观测

ERP 的一致性来自"可补偿",不是"强锁定"


2. 总体架构模型(升级后)

复制代码
┌──────────────────────────┐
│ ScopedValue               │
│ trace / tenant / operator │
└────────────▲─────────────┘
             │
┌────────────┴─────────────┐
│ Local Pipeline            │  ← 单服务内顺序 + 本地回滚
└────────────▲─────────────┘
             │
┌────────────┴─────────────┐
│ Saga Orchestrator         │  ← 跨服务编排
└────────────▲─────────────┘
             │
┌────────────┴─────────────┐
│ Remote Service Pipelines  │  ← 各服务独立 Pipeline
└──────────────────────────┘

3. 核心设计原则(强制)

3.1 单服务内:Pipeline

  • 强类型 I → O

  • 明确顺序

  • 本地 RollbackAction

3.2 跨服务:Saga Step

  • 明确 Forward / Compensate

  • 允许异步

  • 允许失败重试


4. Saga 的最小抽象模型(标准)

4.1 SagaStep 定义

复制代码
public interface SagaStep<C> {

    void forward(C context);

    void compensate(C context);
}

4.2 SagaContext(跨服务业务上下文)

复制代码
public record SagaContext(
    String sagaId,
    String docNo
) {}

约束:

  • 只能放 全局业务标识

  • 禁止放中间结果

  • 禁止放服务私有对象


5. Pipeline × Saga 的结合点(关键)

5.1 每个 SagaStep 内部 = 一个 Local Pipeline

复制代码
SagaStep
 ├─ Pipeline (本服务)
 │   ├─ 校验
 │   ├─ 执行
 │   └─ 本地 rollbackActions
 └─ compensate()

5.2 示例:库存服务 SagaStep

复制代码
public class StockSagaStep implements SagaStep<SagaContext> {

    public void forward(SagaContext ctx) {
        executionPipeline.execute(
            new ExecuteInput(ctx.docNo())
        );
    }

    public void compensate(SagaContext ctx) {
        rollbackPipeline.execute(
            new RollbackInput(ctx.docNo())
        );
    }
}

⚠️ compensate 不是简单反调用

独立设计的补偿语义


6. Saga Orchestrator(编排器)

6.1 顺序 Saga(ERP 最常见)

复制代码
public class SagaOrchestrator {

    private final List<SagaStep<SagaContext>> steps;

    public void execute(SagaContext ctx) {
        List<SagaStep<SagaContext>> executed = new ArrayList<>();

        try {
            for (SagaStep step : steps) {
                step.forward(ctx);
                executed.add(step);
            }
        } catch (Exception e) {
            rollback(executed, ctx);
            throw e;
        }
    }

    private void rollback(
        List<SagaStep<SagaContext>> steps,
        SagaContext ctx
    ) {
        for (int i = steps.size() - 1; i >= 0; i--) {
            steps.get(i).compensate(ctx);
        }
    }
}

6.2 并行 Saga(可选进阶)

  • 用于:

    • 多仓库存冻结

    • 多账户预扣

  • 要求:

    • 幂等

    • 独立补偿


7. ERP 场景完整示例(销售出库)

复制代码
销售出库 Saga
 ├─ 库存服务(扣库存)
 ├─ 财务服务(记应收)
 ├─ 物流服务(生成发货单)

失败场景:

  • 物流失败

    → 回滚:财务冲销 → 库存回补


8. Saga + ScopedValue 的边界(再次强调)

ScopedValue 允许:

  • traceId

  • tenantId

  • operator

ScopedValue 禁止:

  • saga 执行状态

  • step 执行结果

  • 是否已补偿

Saga 的状态必须持久化,而不是隐式存在


9. Saga 状态持久化(强烈推荐)

9.1 SagaInstance 表(示意)

字段 说明
saga_id 全局唯一
doc_no 单据号
status RUNNING / COMPENSATING / DONE
current_step 当前步骤
created_at 创建时间

9.2 SagaStepInstance 表

字段 说明
saga_id 关联
step_name 库存 / 财务
status DONE / FAILED / COMPENSATED
retry_count 重试次数

10. 失败与重试策略(ERP 必须)

场景 策略
forward 失败 触发补偿
compensate 失败 重试 + 人工介入
服务不可达 延迟重试
重复请求 幂等拒绝

11. 与三 Pipeline 的最终映射关系

层级 职责
审核 Pipeline 是否允许启动 Saga
执行 Pipeline SagaStep.forward
回滚 Pipeline SagaStep.compensate

12. 架构红线(必须写进规范)

🚫 禁止一个 SagaStep 内跨多个业务域

🚫 禁止 SagaContext 承载中间业务数据

🚫 禁止用消息最终一致掩盖不可回滚设计


13. 一句话架构总结(非常重要)

Pipeline 保证"一步不乱",
Saga 保证"走错能退"。

ERP 的核心竞争力,
来自"复杂业务的可逆性"。

相关推荐
元拓数智8 小时前
智能分析落地卡壳?先补好「数据关系+语义治理」这层技术基建
大数据·分布式·ai·spark·数据关系·语义治理
GIS数据转换器12 小时前
农村生活污水治理智慧管控平台
大数据·人工智能·分布式·数据分析·生活·智慧城市
Trouvaille ~14 小时前
【Redis篇】初识 Redis:特性、应用场景与版本演进
数据结构·数据库·redis·分布式·缓存·中间件·持久化
米高梅狮子15 小时前
Ceph 分布式存储 部署
linux·运维·数据库·分布式·ceph·docker·华为云
郭龙_Jack15 小时前
跨境电商 平台 - ERP - 内部子系统 交互方式总图
分布式·教育电商
喝醉酒的小白16 小时前
Kafka 集群应急故障排查手册
分布式·kafka
无籽西瓜a16 小时前
【西瓜带你学Kafka | 第八期】 Kafka的主从同步、消息可靠性、流处理与顺序消费(文含图解)
java·分布式·后端·kafka·消息队列·mq
qqVHU16 小时前
kafka笔记
笔记·分布式·kafka
醉颜凉16 小时前
Kafka 消息过期时间设置与清理机制全解析
分布式·kafka·linq
犬小哈16 小时前
滴滴二面:你项目为什么选择 RocketMQ,而不是 Kafka? 我:支支吾吾....
分布式·kafka·rocketmq