LunaTranslator 视觉小说实时翻译:下载部署、首次启动与报错自查终极指南
2026/11/3 10:19:51
分布式 SAGA 模式全解与 Java 入门示例
术语更正:本文讨论的是分布式事务的SAGA 模式(非“sage”)。SAGA 通过将一个跨服务的长事务拆分为多个本地事务,并在失败时按逆序执行补偿事务,实现最终一致性。它特别适合长事务、复杂流程、可接受短暂中间状态的业务场景,如电商下单全流程、物流履约、金融审批等。
一、核心概念与适用场景
| 方案 | 一致性 | 性能 | 业务侵入 | 典型场景 |
|---|---|---|---|---|
| 2PC/3PC | 强一致 | 低 | 低(依赖 XA) | 短事务、强一致核心转账 |
| TCC | 最终一致 | 高 | 高(Try/Confirm/Cancel) | 短事务、高并发、多资源 |
| SAGA | 最终一致 | 中高 | 低(新增补偿) | 长事务、复杂流程 |
| 本地消息表 | 最终一致 | 高 | 低 | 异步通知、简单流程 |
二、两种实现模式图解与对比
示意时序(简化):
编排式: LT1→发“T1成功”→LT2→发“T2成功”→LT3 若 LT2 失败→发“T2失败”→LT1 执行 CT1 协同式: 协调器→LT1→LT2→LT3 若 LT2 失败→协调器→CT2→CT1三、Java 极简示例 协调式 SAGA(无框架)
目标:模拟“扣款 → 扣库存”,失败则“恢复库存 → 冲正扣款”。强调幂等与防悬挂。
publicclassSagaContext{publicfinalStringsagaId=java.util.UUID.randomUUID().toString();publicfinalStringbusinessKey="order-1001";// 可扩展:超时时间、重试次数、状态等}publicinterfaceSagaStep{// 正向本地事务:true=成功,false=失败booleanexecute(SagaContextctx);// 补偿事务:true=补偿成功,false=需重试/告警booleancompensate(SagaContextctx);}importjava.math.BigDecimal;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.atomic.AtomicInteger;publicclassAccountStepimplementsSagaStep{// 模拟账户余额(生产请用 DB)privatestaticfinalConcurrentHashMap<String,BigDecimal>BALANCE=newConcurrentHashMap<>();// 幂等与防悬挂:sagaId -> 已执行动作(避免重复执行/补偿后正向再执行)privatestaticfinalConcurrentHashMap<String,String>EXEC_LOG=newConcurrentHashMap<>();static{BALANCE.put("A001",newBigDecimal("1000"));}@Overridepublicbooleanexecute(SagaContextctx){Stringdone=EXEC_LOG.putIfAbsent(ctx.sagaId+":minus","1");if(done!=null)returntrue;// 幂等:已执行过BigDecimalcur=BALANCE.get("A001");if(cur.compareTo(newBigDecimal("100"))<0)returnfalse;BALANCE.put("A001",cur.subtract(newBigDecimal("100")));System.out.printf("[Account] 扣款成功,余额=%s,sagaId=%s%n",BALANCE.get("A001"),ctx.sagaId);returntrue;}@Overridepublicbooleancompensate(SagaContextctx){// 防悬挂:若正向未执行过,也要记录补偿痕迹,避免正向后补执行Stringpend=EXEC_LOG.putIfAbsent(ctx.sagaId+":compMinus","1");if("1".equals(pend)){System.out.printf("[Account] 补偿已记录或执行过,sagaId=%s%n",ctx.sagaId);returntrue;}BigDecimalcur=BALANCE.get("A001");BALANCE.put("A001",cur.add(newBigDecimal("100")));System.out.printf("[Account] 冲正成功,余额=%s,sagaId=%s%n",BALANCE.get("A001"),ctx.sagaId);returntrue;}}publicclassInventoryStepimplementsSagaStep{// 模拟库存(生产请用 DB)privatestaticfinalConcurrentHashMap<String,AtomicInteger>STOCK=newConcurrentHashMap<>();privatestaticfinalConcurrentHashMap<String,String>EXEC_LOG=newConcurrentHashMap<>();static{STOCK.put("P100",newAtomicInteger(10));}@Overridepublicbooleanexecute(SagaContextctx){Stringdone=EXEC_LOG.putIfAbsent(ctx.sagaId+":deduct","1");if(done!=null)returntrue;AtomicIntegers=STOCK.get("P100");if(s.decrementAndGet()<0){// 回滚本地变更(演示用,生产需事务内操作)s.incrementAndGet();returnfalse;}System.out.printf("[Inventory] 扣减库存成功,库存=%d,sagaId=%s%n",s.get(),ctx.sagaId);returntrue;}@Overridepublicbooleancompensate(SagaContextctx){Stringpend=EXEC_LOG.putIfAbsent(ctx.sagaId+":compDeduct","1");if("1".equals(pend)){System.out.printf("[Inventory] 补偿已记录或执行过,sagaId=%s%n",ctx.sagaId);returntrue;}STOCK.get("P100").incrementAndGet();System.out.printf("[Inventory] 恢复库存成功,库存=%d,sagaId=%s%n",STOCK.get("P100").get(),ctx.sagaId);returntrue;}}importjava.util.ArrayList;importjava.util.List;publicclassSagaCoordinator{privatefinalList<SagaStep>steps=newArrayList<>();publicSagaCoordinatoraddStep(SagaStepstep){steps.add(step);returnthis;}publicvoidexecute(SagaContextctx){List<Integer>done=newArrayList<>();try{for(inti=0;i<steps.size();i++){if(!steps.get(i).execute(ctx)){thrownewRuntimeException("步骤["+i+"]执行失败,触发回滚");}done.add(i);}System.out.printf("[Saga] 执行成功,sagaId=%s%n",ctx.sagaId);}catch(Exceptionex){System.out.printf("[Saga] 执行失败,开始补偿,sagaId=%s,原因=%s%n",ctx.sagaId,ex.getMessage());// 逆序补偿for(inti=done.size()-1;i>=0;i--){booleancompOk=steps.get(i).compensate(ctx);if(!compOk){System.err.printf("[Saga] 补偿步骤[%d]失败,需人工介入,sagaId=%s%n",i,ctx.sagaId);}}}}publicstaticvoidmain(String[]args){SagaContextctx=newSagaContext();newSagaCoordinator().addStep(newAccountStep()).addStep(newInventoryStep()).execute(ctx);}}ConcurrentHashMap.putIfAbsent记录已执行动作。四、生产落地要点与框架选型
五、常见问题快速排查清单