Node.js对多分布式数据目标实现事务控制的方案咨询
Node.js多数据源分布式事务实现方案
你遇到的是典型的跨服务、跨数据源分布式事务场景,针对存在不可直接回滚的Rest API调用的情况,以下是可落地的技术方案:
方案1:Saga补偿事务模式(最适配当前场景)
Saga是业界针对长事务、跨服务事务的主流落地方案,核心逻辑是为每个执行步骤定义对应的逆操作(补偿操作),执行失败时逆序触发已完成步骤的补偿,实现全局回滚:
- 首先为三个步骤分别定义补偿操作:
writeToMySql(data)对应补偿:deleteMySqlRelatedRecord(data),删除本次写入的关联数据postRestApi(data)对应补偿:需要对接的Rest API服务提供幂等的作废/删除接口,比如提交的是订单就调用取消订单接口,提交的是用户数据就调用删除对应临时数据接口writeToSqlServer(data)对应补偿:deleteSqlServerRelatedRecord(data),删除本次写入的关联数据
- 执行逻辑:
- 按顺序执行三个正向操作,每执行成功一个就记录执行日志
- 任意步骤执行失败时,按照和执行顺序相反的顺序,调用已成功步骤的补偿操作
- 举例:Step3执行失败时,先触发Step2的补偿接口,再触发Step1的补偿操作,最终三个步骤都回到执行前的状态
- 注意点:所有正向操作、补偿操作都必须实现幂等性,避免重试/重复调用导致数据异常。
方案2:TCC(Try-Confirm-Cancel)模式(适合强一致性要求场景)
如果你的业务对数据一致性要求更高,不允许中间状态对外暴露,可以采用TCC模式:
- Try阶段:三个步骤都只做资源预留,不正式生效数据:
- MySQL写入标记为「待确认」状态的数据
- Rest API调用预提交接口,预留对应资源,不正式生效
- SQL Server同样写入标记为「待确认」状态的数据
- Confirm阶段:所有Try操作全部成功后,依次调用三个步骤的确认接口,把预留的资源正式生效
- Cancel阶段:任意Try操作失败,依次调用已成功Try步骤的Cancel接口,释放预留资源
- 优势:不会出现半生效的中间数据,一致性更强;缺点是需要三个服务都支持Try/Confirm/Cancel三类接口,对Rest API的改造要求更高。
方案3:本地消息表+最终一致性(适合对实时一致性要求不高的场景)
如果业务允许短时间内的数据不一致,可以采用更低复杂度的最终一致性方案:
- 在本地(比如你的MySQL实例)新建一张事务执行状态表,记录本次操作的ID、三个步骤的执行状态、重试次数等信息
- 按顺序执行三个步骤,每执行成功一个就更新状态表中对应步骤的状态为成功
- 任意步骤执行失败时,启动后台定时任务,按策略重试失败的步骤,或者重试对应的补偿操作,直到所有步骤要么全部执行成功,要么全部完成回滚,最终达到一致状态
特殊场景兼容
如果对接的Rest API完全不提供任何撤销/作废接口,你可以调整执行顺序,把postRestApi(data)放在第一个执行,后续再执行两个数据库操作:如果后续数据库操作失败,最多需要处理Rest API的回滚;如果Rest API执行失败,还没执行后续数据库操作,不需要额外回滚。
内容的提问来源于stack exchange,提问作者phanlh
相关产品推荐
相关产品推荐

