分布式事务(网上资料整理)

参考:拜托,面试请不要再问我TCC分布式事务的实现原理!
参考:分布式系统面试题:分布式事务解决方案?
参考:分布式事务之说说TCC事务
参考:突破Java面试(44)-分布式事务解决方案

1.什么是分布式事务

咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。
那对一个订单支付之后,我们需要做下面的步骤:

  • 更改订单的状态为“已支付”
  • 扣减商品库存
  • 给会员增加积分
  • 创建销售出库单通知仓库发货
    在这里插入图片描述

上述这几个步骤,要么一起成功,要么一起失败, 必须是一个整体性的事务 。

2.两阶段提交方案/XA方案

也叫做两阶段提交事务方案,有一个事务管理器,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
这种分布式事务方案,比较适合单块应用中,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发场景

如果你要操作别的服务对应的库,不允许直连别的服务的库,违反微服务架构的规范,你随便交叉胡乱访问,几百个服务的话,全体乱套,这样的一套服务是没法管理的,没法治理的,可能会出现数据被别人改错,自己的库被别人写挂等情况。

如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。
在这里插入图片描述

3.TCC 方案

TCC 的全称是:Try、Confirm、Cancel。

  • Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留。
  • Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
  • Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)

Try操作是先把多个应用中的业务资源预留和锁定住,为后续的确认打下基础,类似的,DML操作要锁定数据库记录行,持有数据库资源;
Confirm操作是在Try操作中涉及的所有应用均成功之后进行确认,使用预留的业务资源,和Commit类似;
Cancel则是当Try操作中涉及的所有应用没有全部成功,需要将已成功的应用进行取消(即Rollback回滚)。其中Confirm和Cancel操作是一对反向业务操作。

在这里插入图片描述

4.本地消息表

1.实现

  • A系统在本地一个事务里操作的同时,插入一条数据到消息表
  • 接着A系统将这个消息发送到MQ
  • B系统接收到消息后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息
  • B系统执行成功后,就会更新自己本地消息表的状态以及A系统消息表的状态
  • 如果B系统处理失败,那么就不会更新消息表状态,那么此时A系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到MQ中去,让B再处理

2.优点

这个方案保证了最终一致性,哪怕B事务失败了,但是A会不断重发消息,直到B那边成功为止

3.缺点

最大的问题就在于严重依赖于数据库的消息表来管理事务,这个会导致高并发场景无力,难以扩展呢,一般确实很少用
在这里插入图片描述

5.可靠消息最终一致性方案

  • 主动方应用先把消息发给消息中间件,消息状态标记为“待确认”;
  • 消息中间件收到消息后,把消息持久化到消息存储中,但并不向被动方应用投递消息;
  • 消息中间件返回消息持久化结果(成功/失败),主动方应用根据返回结果进行判断如何进行业务操作处理:
    • 失败:放弃业务操作处理,结束(必要时向上层返回失败结果);
    • 成功:执行业务操作处理;
  • 业务操作完成后,把业务操作结果(成功/失败)发送给消息中间件;
  • 消息中间件收到业务操作结果后,根据业务结果进行处理;
    • 失败:删除消息存储中的消息,结束;
    • 成功:更新消息存储中的消息状态为“待发送(可发送)”,紧接着执行消息投递;
  • 前面的正向流程都成功后,向被动方应用投递消息;
  • 被动方需要保证消息的幂等性,并执行对应的业务逻辑
    • 成功:被动方消费成功之后修改Mq的消息状态
    • 失败:MQ自己会负责重推消息,直到消费成功。(基于消息的最终一致性方案必须保证消费端在业务上的操作没障碍,它只允许系统异常的失败,不允许业务上的失败)
      在这里插入图片描述
      在这里插入图片描述

6. 最大努力通知方案

  • 系统A本地事务执行完后,发送一个消息到MQ
  • 有一专门消费MQ的最大努力通知服务,会消费MQ,然后写入数据库中记录下来,亦可是放入内存队列,接着调用系统B的接口
  • 若系统B执行成功就ok;若系统B执行失败,那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行才放弃
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值