分布式事务产生的原因

1. 数据库分库分表

        当数据库单表数据量超过2000W,就要考虑分库分表,这时候,如果一个操作既访问01库,又访问02库,而且要保证数据的一致性,那么就要用到分布式事务。

分布式事务常见解决方案

2. 应用服务化

         业务的服务化。比如原来单机支撑的应用服务,拆解为一块一块独立的服务,例如用户中心、订单中心、账户中心、库存中心。对于订单中心,有专门的数据库存储订单信息,用户中心也有专门的数据库存储用户信息,库存中心也会有专门的数据库存储库存信息。这时候如果要同时对订单进行操作,那么就会涉及到订单数据库和账户数据库,为了保证数据一致性,就需要用到分布式事务。

分布式事务常见解决方案

行业中常见解决方案

1. 本地消息表(异步确保)

本地消息表这种实现方式应该是业界使用最多的,其核心思想是将分布式事务拆分成本地事务进行处理,这种思路是来源于ebay。

基本思路:

  • 消息生产方:需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
  • 消息消费方:需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
  • 生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。如果有靠谱的自动对账补账逻辑,这种方案还是非常实用的。

分布式事务常见解决方案

2. 两阶段提交

XA是X/Open CAE Specification (Distributed Transaction Processing)模型中定义的TM(Transaction Manager)与RM(Resource Manager)之间进行通信的接口。

两阶段提交是XA的标准实现。它将分布式事务的提交拆分为2个阶段:prepare和commit/rollback。

在XA规范中,数据库充当RM角色,应用需要充当TM的角色,即生成全局的txId,调用XAResource接口,把多个本地事务协调为全局统一的分布式事务。

XA中有两个重要的概念:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。XA实现分布式事务的原理如下:

分布式事务常见解决方案

特点:

        XA协议比较简单,目前很多商业数据库(Oracle,DB2、MySQL从5开始支持)都实现XA协议,使用分布式事务的成本也比较低。

        但是,XA也有致命的缺点,那就是性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想,mysql的XA实现,没有记录prepare阶段日志,主备切换会导致主库与备库数据不一致。许多nosql也没有支持XA,这让XA的应用场景变得非常狭隘。在prepare阶段需要等待所有参与子事务的反馈,因此可能造成数据库资源锁定时间过长,不适合并发高以及子事务生命周长较长的业务场景。两阶段提交这种解决方案属于牺牲了一部分可用性来换取的一致性。

补充:二阶段提交协议的主要缺点:

       同步阻塞:二阶段提交协议存在的最明显也是最大的问题就是同步阻塞,这会极大地限制分布式系统的性能。在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。

       单点问题:一旦协调者出现问题,整个二阶段提交流程将无法运转。

       数据不一致:在二阶段的第二个阶段(执行事务提交)的时候,当协调者向所有的参与者发送Commit请求之后,发生了局部网络异常或者协调者在尚未发送完Commit请求之前自身发生崩溃,最终只有部分参与者收到了Commit请求。于是这部分收到了Commit请求的参与者就会进行事务提交,而其他没有收到Commit请求的参与者无法进行事务提交,这样就出现数据不一致。

3. 事务消息+最终一致性

事务消息作为一种异步确保型事务, 将两个事务分支通过MQ进行异步解耦,事务消息的设计流程同样借鉴了两阶段提交理论。

  • 事务发起方首先发送prepare消息到MQ。

  • 在发送prepare消息成功后执行本地事务。

  • 根据本地事务执行结果返回commit或者是rollback。

  • 如果消息是rollback,MQ将删除该prepare消息不进行下发,如果是commit消息,MQ将会把这个消息发送给consumer端。

  • 如果执行本地事务过程中,执行端挂掉,或者超时,MQ将会不停的询问其同组的其它producer来获取状态。

  • Consumer端的消费成功机制有MQ保证。

基于消息中间件的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作,其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了,这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功,这样就变相地实现了A与B的分布式事务

分布式事务常见解决方案

特点:第三方的MQ是支持事务消息的,比如RocketMQ,但是市面上一些主流的MQ都是不支持事务消息的,比如 RabbitMQ 和 Kafka 都不支持。

4. 补偿事务(TCC)

TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。TCC模型是把锁的粒度完全交给业务处理。它分为三个阶段:

  • Try 阶段主要是对业务系统做检测及资源预留

  • Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。

  • Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

特点:TCC模型对业务的侵入强,改造的难度大。

 

扩展阅读:https://www.cnblogs.com/bluemiaomiao/p/11216380.html

相关文章:

  • 2022-12-23
  • 2021-08-22
  • 2021-06-18
  • 2022-12-23
  • 2021-06-01
  • 2022-12-23
  • 2021-05-19
猜你喜欢
  • 2021-11-03
  • 2021-12-02
  • 2022-12-23
  • 2021-04-04
相关资源
相似解决方案