分布式事务算法——Saga 分布式事务全面解析

在这里插入图片描述

Java Saga 分布式事务全面解析

一、Saga 核心原理与特性
1. 长事务处理流程
OrderService PaymentService InventoryService 扣款 成功 扣库存 失败 退款补偿 OrderService PaymentService InventoryService
2. 核心特性对比
特性 Saga TCC 2PC
事务模式 最终一致性 强一致性 强一致性
锁机制 无锁 资源预留 数据库锁
实现复杂度
适用场景 长事务流程 短事务 单库事务
补偿机制 显式补偿 自动回滚 自动回滚
二、Java 实现核心组件
1. Saga 协调器设计
public class SagaCoordinator {
    
    
    private SagaLogStore logStore;
    
    // 启动Saga事务
    public String begin(List<SagaStep> steps) {
    
    
        String sagaId = generateSagaId();
        logStore.logStart(sagaId, steps);
        return sagaId;
    }
    
    // 执行正向操作
    public void executeStep(String sagaId, SagaStep step) {
    
    
        try {
    
    
            step.getTargetService().execute(step.getParams());
            logStore.logStepSuccess(sagaId, step);
        } catch (Exception e) {
    
    
            logStore.logStepFailure(sagaId, step);
            compensate(sagaId);
        }
    }
    
    // 执行补偿操作
    private void compensate(String sagaId) {
    
    
        List<SagaStep> steps = logStore.getSteps(sagaId);
        Collections.reverse(steps);
        steps.forEach(step -> {
    
    
            if (step.isCompleted()) {
    
    
                step.getTargetService().compensate(step.getParams());
            }
        });
    }
}
2. Saga 步骤定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SagaStep {
    
    
    String compensationMethod(); // 补偿方法名
    int timeout() default 60;    // 超时时间(秒)
    int retries() default 3;     // 重试次数
}
三、业务服务实现示例
1. 订单服务实现
public class OrderService {
    
    
    @SagaStep(compensationMethod = "cancelOrder", 
             timeout = 30, 
             retries = 3)
    public void createOrder(Order order) {
    
    
        // 创建订单记录
        orderRepository.save(order);
    }
    
    public void cancelOrder(Order order) {
    
    
        // 取消订单补偿
        order.setStatus(OrderStatus.CANCELLED);
        orderRepository.save(order);
    }
}
2. 支付服务实现
public class PaymentService {
    
    
    @SagaStep(compensationMethod = "refundPayment",
             timeout = 45)
    public void deductPayment(PaymentRequest request) {
    
    
        // 执行扣款操作
        paymentClient.deduct(request);
    }
    
    public void refundPayment(PaymentRequest request) {
    
    
        // 退款补偿操作
        paymentClient.refund(request);
    }
}
四、事务协调流程实现
1. 流程编排器
public class OrderProcessOrchestrator {
    
    
    @Autowired
    private SagaCoordinator coordinator;
    
    public void processOrder(Order order) {
    
    
        List<SagaStep> steps = Arrays.asList(
            new SagaStep(OrderService.class, "createOrder", order),
            new SagaStep(PaymentService.class, "deductPayment", order.getPaymentRequest()),
            new SagaStep(InventoryService.class, "deductInventory", order.getItems())
        );
        
        String sagaId = coordinator.begin(steps);
        steps.forEach(step -> coordinator.executeStep(sagaId, step));
    }
}
2. 异常处理拦截器
@Aspect
@Component
public class SagaExceptionAspect {
    
    
    @Autowired
    private SagaCoordinator coordinator;
    
    @AfterThrowing(pointcut = "@annotation(SagaStep)", throwing = "ex")
    public void handleStepFailure(JoinPoint jp, Exception ex) {
    
    
        String sagaId = SagaContext.getCurrentSagaId();
        SagaStep step = getStepAnnotation(jp);
        coordinator.compensate(sagaId);
    }
}
五、事务恢复机制
1. 事务日志存储设计
public interface SagaLogStore {
    
    
    void logStart(String sagaId, List<SagaStep> steps);
    void logStepSuccess(String sagaId, SagaStep step);
    void logStepFailure(String sagaId, SagaStep step);
    List<SagaStep> getSteps(String sagaId);
    List<String> findUnfinishedSagas();
}

// 数据库实现示例
public class JdbcSagaLogStore implements SagaLogStore {
    
    
    // 使用事务表记录状态
    // CREATE TABLE saga_log (
    //   saga_id VARCHAR(64) PRIMARY KEY,
    //   status VARCHAR(20),
    //   created_at TIMESTAMP
    // )
}
2. 定时恢复服务
public class SagaRecoveryService {
    
    
    @Scheduled(fixedRate = 60000)
    public void recoverUnfinishedSagas() {
    
    
        List<String> sagaIds = logStore.findUnfinishedSagas();
        sagaIds.forEach(sagaId -> {
    
    
            List<SagaStep> steps = logStore.getSteps(sagaId);
            SagaStatus status = calculateRecoveryStatus(steps);
            if (status == SagaStatus.ABORTED) {
    
    
                coordinator.compensate(sagaId);
            } else {
    
    
                resumeExecution(sagaId, steps);
            }
        });
    }
}
六、生产级优化策略
1. 幂等性保证机制
public class IdempotentValidator {
    
    
    private Set<String> processedRequests = new ConcurrentHashSet<>();
    
    public boolean checkAndRecord(String requestId) {
    
    
        return processedRequests.add(requestId);
    }
    
    @Scheduled(fixedRate = 3600000)
    public void cleanExpiredRequests() {
    
    
        // 清理24小时前的记录
    }
}
2. 异步补偿执行
public class AsyncCompensationExecutor {
    
    
    private ExecutorService threadPool = Executors.newFixedThreadPool(10);
    
    public void asyncCompensate(String sagaId, List<SagaStep> steps) {
    
    
        threadPool.submit(() -> {
    
    
            steps.parallelStream().forEach(step -> {
    
    
                try {
    
    
                    executeCompensationWithRetry(step);
                } catch (Exception e) {
    
    
                    alertCompensationFailure(step);
                }
            });
        });
    }
    
    private void executeCompensationWithRetry(SagaStep step) {
    
    
        // 指数退避重试机制
    }
}
七、监控与追踪方案
1. 监控指标设计
public class SagaMetrics {
    
    
    // 事务成功率统计
    private Meter successMeter = new Meter();
    
    // 补偿操作统计
    private Counter compensationCounter = new Counter();
    
    // 耗时分布统计
    private Histogram durationHistogram = new Histogram();
    
    public void recordSuccess(long duration) {
    
    
        successMeter.mark();
        durationHistogram.update(duration);
    }
}
2. 分布式追踪集成
public class SagaTracingInterceptor implements HandlerInterceptor {
    
    
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) {
    
    
        String traceId = request.getHeader("X-Trace-ID");
        if (traceId == null) {
    
    
            traceId = generateTraceId();
        }
        MDC.put("traceId", traceId);
        return true;
    }
}
八、典型应用场景
1. 电商订单流程
创建订单
扣减库存
支付扣款
生成发货单
成功?
流程完成
库存补偿
支付退款
2. 酒店预订系统
public class HotelBookingSaga {
    
    
    @SagaStep(compensationMethod = "cancelReservation")
    public void reserveRoom(ReservationRequest request) {
    
    
        // 预订房间
    }
    
    @SagaStep(compensationMethod = "releaseHold")
    public void holdPayment(PaymentRequest request) {
    
    
        // 预授权扣款
    }
    
    public void cancelReservation(ReservationRequest request) {
    
    
        // 取消房间预订
    }
    
    public void releaseHold(PaymentRequest request) {
    
    
        // 释放预授权
    }
}
九、最佳实践总结
  1. 设计原则

    • 每个正向操作必须定义补偿操作
    • 保持补偿操作幂等性
    • 设置合理的事务超时时间
  2. 恢复策略

    • 定期扫描未完成事务
    • 实现补偿重试机制
    • 记录详细事务日志
  3. 性能优化

    • 使用异步补偿执行
    • 批量处理事务日志
    • 优化服务间通信
  4. 监控指标

    78% 15% 5% 2% Saga事务状态分布 成功 失败已补偿 补偿失败 进行中
  5. 容灾方案

    • 协调器集群部署
    • 多数据中心部署
    • 事务日志多副本存储

完整实现示例参考:java-saga-framework(示例仓库)

Saga模式通过将长事务拆分为多个本地事务,配合补偿机制实现最终一致性,适用于需要处理复杂业务流程的分布式系统。实际实施时需重点关注服务设计的幂等性、完善的监控体系和可靠的事务恢复机制,可结合Apache ServiceComb Saga、Eventuate等成熟框架进行二次开发。

更多资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

本文发表于【纪元A梦】,关注我,获取更多免费实用教程/资源!