当前位置: 首页 > news >正文

微服务分布式事务解决方案梳理

核心问题:为什么需要分布式事务?

在单体应用中,我们通常使用本地事务(Local Transaction)和 ACID 特性(原子性、一致性、隔离性、持久性)来保证数据一致性。数据库本身就能处理这一切。

但在微服务架构中,一个业务操作通常会跨越多个服务,每个服务都有自己的独立数据库(这是微服务设计的一个核心原则——数据库按服务拆分)。这就意味着,你无法再用一个本地事务来涵盖整个操作。

例如“创建订单”流程:

1、订单服务:在 orders_db 中创建订单记录,状态为“待支付”。

2、库存服务:在 inventory_db 中扣减相应商品的库存。

3、用户服务:在 users_db 中给用户增加积分。

这三个步骤必须在逻辑上成为一个“事务”:要么全部成功,要么全部失败。如果订单创建成功但库存扣减失败,就会导致超卖。这就是典型的分布式事务问题。

理论基础:CAP 与 BASE 理论

在讨论解决方案前,必须先理解这两个理论,它们是分布式系统设计的基石。
1、CAP 定理

  • 一致性 (Consistency):所有节点在同一时间看到的数据是一致的。

  • 可用性 (Availability):每个请求都能得到响应(不保证是最新数据)。

  • 分区容错性 (Partition Tolerance):系统在遇到网络分区(节点间无法通信)时仍然能继续工作。

  • CAP 定理指出,分布式系统无法同时满足这三个特性,最多只能满足其中两项。 由于网络分区无法避免,所以通常必须在 CPAP之间做选择。

  • 这对分布式事务意味着:强一致性(CP)会牺牲一定的可用性,而高可用性(AP)则通常要求我们放弃强一致性,转而追求最终一致性

2、BASE 理论

  • 它是 CAP 定理中 AP 方向的延伸,是对互联网大规模分布式系统的实践总结。

  • 基本可用 (Basically Available):系统出现故障时,允许损失部分可用性(如响应时间变长、功能降级)。

  • 软状态 (Soft State):允许系统中的数据存在中间状态,并且该中间状态不会影响系统整体可用性。

  • 最终一致性 (Eventually Consistent):经过一段时间后,所有副本的数据会达到一致的状态。

  • BASE 理论是最终一致性事务方案的理论基础

解决方案

分布式事务的解决方案主要分为两大类:强一致性最终一致性

一、强一致性方案

这类方案追求数据的实时一致性,通常较复杂,性能开销大,适用于金融、支付等对一致性要求极高的场景。
1、两阶段提交 (2PC - Two-Phase Commit)

  • 角色:一个协调者 (Coordinator) 和多个参与者 (Participants)(即各个微服务)。

  • 阶段一:准备阶段 (Prepare Phase)

    • 协调者向所有参与者发送事务内容,询问是否可以提交。

    • 参与者执行事务中的所有操作(但不提交),写入 undo/redo 日志,然后锁定资源。

    • 参与者回复协调者:“可以提交” (Yes) 或“无法提交” (No)。

  • 阶段二:提交/回滚阶段 (Commit/Rollback Phase)

    • 如果所有参与者都回复 “Yes”:协调者向所有参与者发送 Commit 命令,参与者正式提交事务,释放锁。

    • 如果任何参与者回复 “No” 或超时:协调者向所有参与者发送 Rollback 命令,参与者利用 undo 日志回滚事务,释放锁。

  • 优点:强一致性,概念简单。

  • 缺点

    • 同步阻塞:所有参与者在等待协调者指令时都处于阻塞状态,资源被锁定,性能差。

    • 单点问题:协调者宕机会导致整个事务阻塞和数据不一致。

    • 数据不一致:在第二阶段,如果部分参与者收到 Commit 后宕机,会导致数据不一致。

2、三阶段提交 (3PC)

  • 2PC 的改进版,引入了超时机制和预提交阶段(CanCommit, PreCommit, DoCommit),减少了阻塞范围,但实现更复杂,且依然无法彻底解决数据不一致问题。实际应用较少。
二、最终一致性方案(推荐)

这是互联网公司更常用的模式,通过补偿机制消息队列来实现数据的最终一致,保证系统的可用性和性能。

1、TCC (Try-Confirm-Cancel)

  • 核心思想:将业务逻辑分为三个操作,由业务代码实现。

  • Try 阶段:资源检查与预留。调用所有服务的 Try 接口,完成业务检查(如检查库存是否充足),并预留关键资源(如冻结库存、冻结优惠券)。

  • Confirm 阶段:确认执行。如果所有服务的 Try 都成功,则进入 Confirm 阶段,调用所有服务的 Confirm 接口,正式提交事务。Confirm 操作需满足幂等性。

  • Cancel 阶段:取消补偿。如果任何服务的 Try 失败,则进入 Cancel 阶段,调用所有服务的 Cancel 接口,释放 Try 阶段预留的资源。Cancel 操作也需满足幂等性。

  • 优点:性能比 2PC 高,数据最终一致。

  • 缺点:对代码侵入性强,需要为每个业务逻辑设计 Try/Confirm/Cancel 三个接口。需要保证 Confirm 和 Cancel 的幂等性空回滚(Try未执行,Cancel被调用)的处理。

2、Saga 事务

核心思想:将一个长事务拆分为多个本地短事务,每个短事务都有对应的补偿操作。

执行方式

  • 正向操作:S1 -> S2 -> S3 (例如:创建订单 -> 扣库存 -> 加积分)

  • 补偿操作:C1 <- C2 <- C3 (例如:删除订单 -> 回滚库存 -> 扣减积分)

  • 协调模式

    • 协同式 (Choreography):每个服务执行完后,产生一个事件来触发下一个服务。如果执行失败,则触发补偿事件。事件流散落在各个服务中,复杂度高。

    • 编排式 (Orchestration):引入一个协调器 (Orchestrator),由它集中管理整个事务的执行顺序和补偿逻辑。逻辑更清晰,易于管理和监控。

  • 优点:一阶段就提交本地事务,无锁,性能高。

  • 缺点:不保证隔离性(可能出现“脏读”),补偿逻辑的实现有一定复杂度。

3、基于消息队列的最终一致性

  • 核心思想:利用消息队列的可靠性投递消费者幂等性来保证最终一致。

  • 典型模式本地消息表
    1、 业务执行与消息发送在同一个本地事务中完成。

    • 例如:订单服务在 orders_db 中创建订单记录,同时在同一事务中向一张本地消息表插入一条“库存扣减”消息。

    2、有一个后台任务轮询本地消息表,将消息发送到 MQ。

    3、库存服务消费 MQ 中的消息,执行扣减库存操作。

    4、 执行成功后,发送一条成功应答(或通过更新状态),订单服务收到后可将本地消息标记为“已发送”或删除。

  • 如果步骤3失败? 消息会重投,直到成功。因此消费者必须实现幂等(判断是否已处理过该消息)。

  • 优点:实现简单,与业务耦合度低,是常用的异步确保型方案。

  • 缺点:消息可能会被重复消费,要求消费者幂等。

4、最大努力通知

  • 适用于对一致性要求不高的场景,如支付结果通知。服务 A 执行完成后,最大努力地(反复重试)向服务 B 发送通知,直到对方成功返回。即使最终不成功,也提供查询接口,让 B 方主动来对账。这是最终一致性的一种柔性解决方案。

总结与选型建议

方案一致性性能复杂度适用场景
2PC强一致低(同步阻塞)传统银行、内部系统,追求强一致
TCC最终一致高(代码侵入)金融交易、资金处理,高一致性要求
Saga最终一致高(无锁)长事务、业务流程多的场景(如旅行订票)
本地消息表最终一致高(异步)绝大多数业务场景,如扣库存、发积分
最大努力通知最终一致第三方回调、支付结果通知
现代微服务架构下的最佳实践:

1、默认首选最终一致性:在绝大多数业务场景下,最终一致性方案(尤其是基于消息队列的)在性能、可用性和复杂度之间取得了最佳平衡。

2、设计幂等性:无论选择哪种方案,服务接口的幂等性是必须考虑的,以防止重试或消息重复消费导致的数据错乱。

3、业务补偿而非技术回滚:接受“事情可能不会一步到位做完”的现实,通过设计补偿操作(取消订单、回滚库存)来纠正错误,而不是依赖数据库的回滚。

4、查询与操作分离:使用**CQRS(命令查询职责分离)**模式,允许读数据短暂滞后于写数据,更好地接受最终一致性模型。

5、必要时才用强一致性:仅在资金、交易等核心链路且无法接受延时一致的情况下,才考虑使用 TCC 或 Saga 等更重但一致性更强的方案。

以上是对微服务分布式事务一点理解、不足之处希望大牛们指点一二!


文章转载自:

http://hjHbeqbK.gLnmm.cn
http://dWifVIPk.gLnmm.cn
http://7ZIuqPjn.gLnmm.cn
http://26gPGlDY.gLnmm.cn
http://PRiwtvEN.gLnmm.cn
http://YmcQPw9V.gLnmm.cn
http://APsL6hOG.gLnmm.cn
http://ZkXdnqTc.gLnmm.cn
http://XSXFj6s1.gLnmm.cn
http://qZsZaE4T.gLnmm.cn
http://EcxbR8bd.gLnmm.cn
http://lsS5NyjT.gLnmm.cn
http://kd11AKZs.gLnmm.cn
http://GZIY50rP.gLnmm.cn
http://w4ryfRdb.gLnmm.cn
http://BiNn0VOt.gLnmm.cn
http://ypHE5NEz.gLnmm.cn
http://IRMR3xCb.gLnmm.cn
http://rFJlhPzy.gLnmm.cn
http://ntYz9l7B.gLnmm.cn
http://X8oyjWr3.gLnmm.cn
http://I9PjhfIF.gLnmm.cn
http://1qvROAdQ.gLnmm.cn
http://fkzK66d2.gLnmm.cn
http://ufnZH4jH.gLnmm.cn
http://NPVQCcW4.gLnmm.cn
http://cy1Tyflk.gLnmm.cn
http://RBNIgvgR.gLnmm.cn
http://GXiTp70r.gLnmm.cn
http://IHYSztor.gLnmm.cn
http://www.dtcms.com/a/386432.html

相关文章:

  • 告别“长明灯”——塔能科技地下车库照明改造的极致节能
  • vue 3 阿里云视频播放器 如何让用户自己给视频添加节点
  • LinkedList 底层实现与 ArrayList 对比分析
  • 滚珠花键在半导体制造设备中承担怎样的核心功能?
  • 服装制造企业痛点解决方案:EFISH-SBC-RK3588 柔性化吊挂调度方案
  • 10cm钢板矫平机:工业制造中的“整形医生”
  • html表单登录模式代码
  • QUIC 协议域名封堵:核心原理、关键技术与实现路径(C/C++代码实现)
  • 8 基于机器学习进行遥感影像的地物分类-以随机森林为例
  • Qt读写SQLite示例
  • Jmeter性能测试之阶梯式场景、波浪式场景、服务器监控
  • 黄昏时刻复古胶片风格人像风光摄影后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • Django ORM多对多关系实战指南
  • 【从零开始java学习|第十七篇】面向对象进阶
  • Three.js 开发实战教程(一):环境搭建与第一个 3D 场景
  • 旅游小程序的功能优势
  • LeetCode:7.接雨水
  • Android 安卓 问题解决记录 腾讯IM和厂商离线推送问题 点击离线推送无法唤醒APP启动页但某些Service服务和Application被启动
  • 动态规划解决系列子序列问题
  • SCADE One vs Scade 6 - 标量积建模比较
  • Next.js 身份验证与授权:使用 NextAuth.js 保护你的应用
  • Spring MVC 的案例小练习
  • 贪心算法与动态规划
  • 香港期权市场的主要参与者有哪些?
  • 系统中间件与云虚拟化-serverless-基于阿里云函数计算的简单邮件发送服务设计与体验
  • 【LLM】GPT-OSS架构变化详解
  • 【开题答辩全过程】以 “寄情绿苑”绿色殡葬服务小程序的设计和实现为例,包含答辩的问题和答案
  • 容器化部署之dockerfile07
  • 一篇读懂Pormise!!【前端ES6】
  • spring-kafka的消息过滤器RecordFilterStrategy