Java Saga 分布式事务全面解析
一、Saga 核心原理与特性
1. 长事务处理流程
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) {
// 释放预授权
}
}
九、最佳实践总结
-
设计原则:
- 每个正向操作必须定义补偿操作
- 保持补偿操作幂等性
- 设置合理的事务超时时间
-
恢复策略:
- 定期扫描未完成事务
- 实现补偿重试机制
- 记录详细事务日志
-
性能优化:
- 使用异步补偿执行
- 批量处理事务日志
- 优化服务间通信
-
监控指标:
-
容灾方案:
- 协调器集群部署
- 多数据中心部署
- 事务日志多副本存储
完整实现示例参考:java-saga-framework(示例仓库)
Saga模式通过将长事务拆分为多个本地事务,配合补偿机制实现最终一致性,适用于需要处理复杂业务流程的分布式系统。实际实施时需重点关注服务设计的幂等性、完善的监控体系和可靠的事务恢复机制,可结合Apache ServiceComb Saga、Eventuate等成熟框架进行二次开发。
更多资源:
http://sj.ysok.net/jydoraemon 访问码:JYAM