Saga实战:Seata与Temporal工作流
Saga实战:Seata与Temporal工作流
Saga模式核心原理
Saga模式将长事务拆分为一系列本地事务,每个事务都有对应的补偿操作。当某个步骤失败时,按逆序执行已完成步骤的补偿操作。Saga有两种实现方式:编排式(Choreography)和协同式(Orchestration)。
正向流程: T1 → T2 → T3 → T4
补偿流程: C4 → C3 → C2 → C1 (当T3失败时)
Seata的Saga实现
Seata是阿里开源的分布式事务解决方案,其Saga模式通过状态机驱动事务流程。每个Saga事务由一系列状态节点组成,支持自动补偿和手动补偿。
// Seata Saga状态机定义
StateMachineConfig config = new StateMachineConfig();
StateMachineEngine engine = new StateMachineEngineImpl(config);
// 定义Saga事务
StateInst s1 = new StateInst();
s1.setName("createOrder");
s1.setType("ServiceTask");
s1.setServiceClass("com.example.OrderService");
s1.setServiceMethod("create");
s1.setCompensateState("cancelOrder");
StateInst s2 = new StateInst();
s2.setName("deductStock");
s2.setType("ServiceTask");
s2.setServiceClass("com.example.StockService");
s2.setServiceMethod("deduct");
s2.setCompensateState("restoreStock");
Temporal工作流实现
Temporal是Uber开源的工作流引擎,使用代码即工作流的方式定义Saga事务,支持长时间运行和复杂编排。
// Temporal Saga工作流
func OrderWorkflow(ctx workflow.Context, order OrderRequest) error {
var orderResult OrderResult
var stockResult StockResult
// 补偿操作列表
compensations := []func(ctx workflow.Context) error{}
// Step 1: 创建订单
err := workflow.ExecuteActivity(ctx, CreateOrderActivity, order).Get(ctx, &orderResult)
if err != nil {
return err
}
compensations = append(compensations, func(ctx workflow.Context) error {
return workflow.ExecuteActivity(ctx, CancelOrderActivity, orderResult.OrderID).Get(ctx, nil)
})
// Step 2: 扣减库存
err = workflow.ExecuteActivity(ctx, DeductStockActivity, orderResult.OrderID).Get(ctx, &stockResult)
if err != nil {
// 执行补偿
for i := len(compensations) - 1; i >= 0; i-- {
compensations[i](ctx)
}
return err
}
compensations = append(compensations, func(ctx workflow.Context) error {
return workflow.ExecuteActivity(ctx, RestoreStockActivity, stockResult.StockID).Get(ctx, nil)
})
return nil
}
Seata vs Temporal对比
| 特性 | Seata | Temporal |
|---|---|---|
| 事务模型 | 状态机驱动 | 代码即工作流 |
| 长事务支持 | 基于数据库轮询 | 基于事件驱动 |
| 语言支持 | Java为主 | 多语言SDK |
| 补偿机制 | 自动/手动补偿 | 代码显式定义 |
| 运维复杂度 | 中等 | 较高 |
| 社区活跃度 | 国内活跃 | 国际活跃 |
补偿事务设计最佳实践
补偿操作必须满足幂等性、可交换性和可补偿性。设计补偿事务时要考虑网络分区、超时、并发等异常场景。建议使用语义锁机制防止脏读,通过事件溯源实现完整的事务审计追踪。