如何选择分布式事务

本文深入解析了五种主流的分布式事务形态,包括基于消息、补偿、TCC、SAGA和2PC的实现方式,探讨了每种形态的适用场景、性能特点及开发成本,帮助开发者根据具体业务需求选择最优方案。

转载自:https://blog.youkuaiyun.com/xiaolang85/article/details/85759536

分布式事务有多种主流形态,包括:

  • 基于消息实现的分布式事务
  • 基于补偿实现的分布式事务
  • 基于TCC实现的分布式事务
  • 基于SAGA实现的分布式事务
  • 基于2PC实现的分布式事务

何时选择单机事务?

  在条件允许的情况下,应该尽可能地使用单机事务,因为单机事务里,无需额外协调其他数据源,减少了网络交互时间消耗以及协调时所需的存储IO消耗,在修改等量业务数据的情况下,单机事务将会有更高的性能。
  但单机数据库由于 业务逻辑解耦等因素进行了数据库垂直拆分、或者由于单机数据库性能压力等因素进行了数据库水平拆分之后,数据分布于多个数据库,这时若需要对多个数据库的数据进行协调变更,则需要引入分布式事务。
  分布式事务的模式有很多种,那究竟要怎么选择适合业务的模式呢?以下我们将从使用场景、性能、开发成本这几个方面进行分析。

何时选择基于消息实现的事务?

  基于消息实现的事务适用于 分布式事务的提交或回滚只取决于事务发起方的业务需求,其他数据源的数据变更跟随发起方进行的业务场景。

  举个例子,假设存在业务规则:某笔订单成功后,为用户加一定的积分。在这条规则里,管理订单数据源的服务为事务发起方,管理积分数据源的服务为事务跟随者。从这个过程可以看到,基于消息队列实现的事务存在以下操作:

  • 订单服务创建订单,提交本地事务
  • 订单服务发布一条消息
  • 积分服务收到消息后加积分

  可以看到它的整体流程是比较简单的,同时业务开发工作量也不大:

  • 编写订单服务里订单创建的逻辑
  • 编写积分服务里增加积分的逻辑

  可以看到该事务形态过程简单,性能消耗小,发起方与跟随方之间的流量峰谷可以使用队列填平,同时业务开发工作量也基本与单机事务没有差别,都不需要编写反向的业务逻辑过程。因此基于消息队列实现的事务是除了单机事务外最优先考虑使用的形态。

何时选择利用补偿实现的事务?

  但是基于消息实现的事务并不能解决所有的业务场景,例如以下场景:某笔订单完成时,同时扣掉用户的现金。
  这里事务发起方是管理订单库的服务,但对整个事务是否提交并不能只由订单服务决定,因为还要确保用户有足够的钱,才能完成这笔交易,而这个信息在管理现金的服务里。这里可以引入基于补偿实现的事务,其流程如下:

  • 创建订单数据,但暂不提交本地事务
  • 订单服务发送远程调用到现金服务,以扣除对应的金额

  上述步骤成功后提交订单库的事务。以上这个是正常成功的流程,异常流程需要回滚的话,将额外发送远程调用到现金服务以加上之前扣掉的金额。

  开发的工作量:

  • 编写订单服务里创建订单的逻辑
  • 编写现金服务里扣钱的逻辑
  • 编写现金服务里补偿返还的逻辑

  可以看到,该事务流程相对于基于消息实现的分布式事务更为复杂,需要额外开发相关的业务回滚方法,也失去了服务间流量削峰填谷的功能。但其仅仅只比基于消息的事务复杂多一点,若不能使用基于消息队列的最终一致性事务,那么可以优先考虑使用基于补偿的事务形态。

何时选择利用TCC实现的事务

  然而基于补偿的事务形态也并非能实现所有的需求,如以下场景:某笔订单完成时,同时扣掉用户的现金,但交易未完成,也未被取消时,不能让客户看到钱变少了。这时可以引入TCC,其流程如下:

  • 订单服务创建订单
  • 订单服务发送远程调用到现金服务,冻结客户的现金
  • 提交订单服务数据
  • 订单服务发送远程调用到现金服务,扣除客户冻结的现金

  以上是正常完成的流程,若为异常流程,则需要发送远程调用请求到现金服务,撤销冻结的金额。
  开发的工作量:

  • 订单服务编写创建订单的逻辑
  • 现金服务编写冻结现金的逻辑
  • 现金服务编写扣除现金的逻辑
  • 现金服务编写解冻现金的逻辑

  TCC实际上是最为复杂的一种情况,其能处理所有的业务场景,但无论出于性能上的考虑,还是开发复杂度上的考虑,都应该尽量避免该类事务。

何时选择利用SAGA实现的事务?

  SAGA可以看做一个异步的、利用队列实现的补偿事务。其适用于无需马上返回业务发起方最终状态的场景,例如:请求已提交,请稍后查询或留意通知 之类。将上述补偿事务的场景用SAGA改写,其流程如下:

  • 订单服务创建最终状态未知的订单记录,并提交事务
  • 现金服务扣除所需的金额,并提交事务
  • 订单服务更新订单状态为成功,并提交事务

  以上为成功的流程,若现金服务扣除金额失败,那么,最后一步订单服务将会更新订单状态为失败。其业务编码工作量比补偿事务多一点,包括以下内容:

  • 订单服务创建初始订单的逻辑
  • 订单服务确认订单成功的逻辑
  • 订单服务确认订单失败的逻辑
  • 现金服务扣除现金的逻辑
  • 现金服务补偿返回现金的逻辑

  但其相对于补偿事务形态有性能上的优势,所有的本地子事务执行过程中,都无需等待其调用的子事务执行,减少了加锁的时间,这在事务流程较多较长的业务中性能优势更为明显。同时,其利用队列进行进行通讯,具有削峰填谷的作用。
  因此该形式适用于不需要同步返回发起方执行最终结果、可以进行补偿、对性能要求较高、不介意额外编码的业务场景。
  但当然SAGA也可以进行稍微改造,变成与TCC类似、可以进行资源预留的形态。

2PC事务

  其适用于参与者较少,单个本地事务执行时间较少,并且参与者自身可用性很高的场景,否则,其很可能导致性能下降严重。

  通过分析可以发现,并不存在一种事务形态能解决所有的问题,需要根据特定的业务场景选择合适的事务形态。甚至于有时需要混合多种事务形态才能更好的完成目标,如 上面提到的 订单、积分、钱包混合的场景:订单的成功与否需要依赖于钱包的余额,但不依赖于积分的多少,因此可以混合基于消息的事务形态以加积分 及 基于补偿的事务形态以确保扣钱成功,从而得到一个性能更好,编码量更少的形态。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值