分布式事务的处理方案

分布式事务的处理方案有多种,每种方案都有其独特的优点和适用场景。以下是一些常见的分布式事务处理方案:

一、两阶段提交(2PC/XA)

  1. 原理

    • 准备阶段:协调者询问参与者是否准备成功,参与者回复结果。
    • 提交阶段:如果事务在每个参与者身上都执行成功了,协调者会发通知让所有参与者提交事务,否则协调者让所有参与者回滚事务。
  2. 优缺点

    • 优点:原理简单,易于理解。
    • 缺点
      • 同步阻塞:所有参与者在等待其他参与者响应的过程中都处于同步堵塞状态,无法进行其他操作。
      • 单点问题:协调者在方案中起到关键作用,发生故障将造成很大影响。
      • 数据不一致:在第二阶段,如果协调者只发送了部分提交消息,此时出现故障,会导致部分参与者提交事务,其他参与者没有提交,造成数据不一致。
      • 并发度低:对资源进行了长时间的锁定。

二、补偿事务(TCC)

  1. 原理

    • 采用补偿机制,针对每一个操作,都会注册一个与其对应的确认和补偿操作。TCC分为三个阶段:
      • Try阶段:对业务系统进行检测和资源预留。
      • Confirm阶段:对业务系统做确认提交。Try阶段执行成功后开始执行Confirm,默认Confirm不会出错。
      • Cancel阶段:在业务执行错误、需要回滚的状态下执行的业务取消,预留资源释放。
  2. 优缺点

    • 优点:与两阶段提交相比,实现及流程相对简单。
    • 缺点
      • 开发量大:需要定义正常操作以及补偿操作。
      • 一致性较弱:可能出现A用户已扣款,但转账最终失败的情况。
      • 对业务侵入性大:需要在业务层面实现,每一个操作都需要实现对应的三个方法。

三、本地消息表(异步确保)

  1. 原理

    • 本地消息表与业务数据表处于同一个数据库中,利用本地事务保证对这两个表的操作满足事务特性,并使用消息队列保证最终一致性。
    • 分布式事务操作的一方完成写业务数据的操作后,向本地消息表发送一个消息,本地事务能保证这个消息一定写入本地消息表中。
    • 将本地消息表中的消息转发到消息队列(如Kafka),如果转发成功则将消息从本地消息表中删除,否则继续重新转发。
    • 分布式事务操作的另一方从消息队列中读取消息,并执行消息中的操作。
  2. 优缺点

    • 优点
      • 避免了分布式事务,实现了最终一致性。
      • 适合对时间不敏感的业务。
    • 缺点
      • 消息表会耦合到业务系统中,增加了系统的复杂性。
      • 需要处理消息队列的可靠性、消息重复投递等问题。

四、Saga事务

  1. 原理

    • 将长事务拆分为多个本地短事务,由Saga事务协调器协调。
    • 如果正常结束则正常完成,如果某个步骤失败,则根据相反顺序依次调用补偿操作。
  2. 优缺点

    • 优点
      • 并发度高,不用像XA事务那样长期锁定资源。
      • 适用于长事务和对中间结果不敏感的业务场景。
    • 缺点
      • 需要定义正常操作以及补偿操作,开发量较大。
      • 一致性较弱,可能出现部分操作成功、部分操作失败的情况。

五、最大努力通知

  1. 原理

    • 系统A本地事务执行完后,发送消息到消息队列。
    • 有一个专门消费消息队列的最大努力通知服务,该服务会消费消息并记录,然后调用系统B的接口。
    • 如果系统B执行失败,最大努力通知服务会定时尝试重新调用系统B,反复N次后如果还是失败就放弃。
  2. 优缺点

    • 优点
      • 实现了最终一致性。
      • 适用于对一致性要求不是特别高的场景。
    • 缺点
      • 可能存在消息丢失或重复投递的问题。
      • 需要处理消息投递的可靠性、幂等性等问题。

六、基于CAP/BASE理论的解决方案

CAP理论指出,分布式系统无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)三个特性,最多只能选两个。BASE理论则是对CAP中一致性和可用性权衡的结果,它追求的是基本业务可用性、柔性状态和最终一致性。基于CAP/BASE理论的解决方案通常是通过牺牲强一致性来换取高可用性和分区容错性,适用于对一致性要求不是特别高但对可用性和容错性要求较高的场景。

综上所述,分布式事务的处理方案各有优缺点,需要根据具体的应用场景和需求来选择合适的方案。在实际应用中,可能还需要结合其他技术手段(如消息队列、分布式锁、分布式缓存等)来共同实现分布式事务的处理。

相关推荐
绝无仅有17 分钟前
未来教育行业的 Go 服务开发解决方案与实践
后端·面试·github
milanyangbo1 小时前
“卧槽,系统又崩了!”——别慌,这也许是你看过最通俗易懂的分布式入门
分布式·后端·云原生·架构
失散131 小时前
分布式专题——1.1 Redis单机、主从、哨兵、集群部署
java·数据库·redis·分布式·架构
UrbanJazzerati2 小时前
掌握 xlwings 的 used_range:高效处理 Excel 数据区域
python·面试·excel
青鱼入云2 小时前
【面试场景题】spring应用启动时出现内存溢出怎么排查
spring·面试·职场和发展
007php0072 小时前
Go语言面试:传值与传引用的区别及选择指南
java·开发语言·后端·算法·面试·golang·xcode
小徐不徐说2 小时前
数据结构基础之队列:数组/链表
c语言·数据结构·算法·链表·面试
Spider_Man2 小时前
从 “不会迭代” 到 “面试加分”:JS 迭代器现场教学
前端·javascript·面试
你我约定有三4 小时前
软件启动时加配置文件 vs 不加配置文件
java·分布式·zookeeper
前端小巷子4 小时前
JS实现丝滑文字滚动
前端·javascript·面试