分布式事务

文章介绍了分布式事务的重要性,详细讲解了XA规范,包括其角色AP、TM、RM以及如何协调事务。接着讨论了二阶段提交(2PC)和三阶段提交(3PC)的流程、优缺点及解决方案,指出2PC可能存在的数据不一致问题。提到了TCC模式作为解决方法,允许在业务层面处理回滚。最后,提到了Seata分布式事务框架,它的AT和TCC模式,并且阐述了RocketMQ的事务消息机制,确保分布式事务的可靠性。
摘要由CSDN通过智能技术生成

一、为什么需要分布式事务:

在这里插入图片描述
分布式事务是指 会涉及到操作多个数据库(服务)的事务。
其实就是将对 同一数据库(服务)事务的概念扩大到了多个数据库(服务)的事务。
目的是为了保证分布式系统中的数据一致性。

二、分布式事务XA规范:

什么是XA规范:

XA规范是一种用于实现分布式事务的标准,它定义了一组接口和协议,用于协调分布式环境下多个资源管理器(Resource Manager)之间的事务操作。
XA规范的全称是"X/Open Distributed Transaction Processing (DTP) XA",最初由X/Open(现在的The Open Group)制定并发布。它提供了两个关键接口:XA接口和RM接口。

其中XA里面有这几个角色:

  • AP(Application,应用程序)
  • TM(Transaction Manager,事务管理器)
  • RM(Resource Manager,资源管理器)

XA规范:就是X/Open DTP定义的 事务协调者 与数据库之间的接口规范,(既接口函数),事务协调者 用它来通知数据库事务的开始、结束以及提交、回滚等操作。

XA规范的实现:分布式集群的情况下,一般加代理层来充当TM的角色,实现对事务的支持。

其中二阶段提交协议(2PC)和三阶段提交协议(3PC)就是根据XA规范这一思想衍生出来的。
两阶段提交主要保证了分布式事务的原子性:既所有节点要么全成功,要么全不成功。

三、二阶段提交(2PC):

3.1 第一阶段:

在这里插入图片描述

  1. 事务协调者(TM)给各个节点发送 执行 指令,然后两个服务开始执行,如果两个服务的业务逻辑都没有问题反馈给事务协调者。这时两个服务的数据还没有提交至数据库。为什么呢?(往下看)
  2. 假如现在事务协调者收到这两个都没有问题。然后事务协调者发送提交指令,两个进行提交。
3.2 第二阶段:

在这里插入图片描述
3. 这个时候两个服务都提交了。(完成事务)
4. 然后我们重新来演示下 第一阶段提交问题。
在这里插入图片描述
5. 看上图,在库存节点的时候内部报错了,响应给协调者,或者说库存节点迟迟不给协调者回应,超出了一定的时间,那么第2阶段就变成回滚报错了。(完成事务)
在这里插入图片描述

3.3 二阶段提交的缺点和解决办法:
  • 事务协调者故障(各个节点的协调会失败)

给事务协调者增加集群

  • 占用数据库连接 (数据库链接阻塞,就是我们的第1步骤,需要等待协调者响应才能提交到数据库)

这个也是可以解决的,就是如果第1阶段都没有问题,那么就直接提交,然后记录数据原来的状态。如果第2阶段如果事务协调者让回滚的话。我们可以根据数据原来的状态直接进行回滚操作,这样就解决了占用链接的问题了。(阿里云的Seata就是这么干的)

  • 网络波动,数据不一致:为什么会产生这个问题呢?
    如果我们的第一阶段都没有问题的话,在第二阶段的时候,
    在这里插入图片描述

这种方式的情况下,只能人工手动解决。。

四、三阶段提交(3PC):

3pc阶段提交示例图:
在这里插入图片描述
其实3pc提交的后两个阶段 pre commit和 do commit 就是2pc提交的方式。那为什么要有3pc提交呢?
3pc的出现其实就为了解决 2pc 的第一步长久占用数据库连接。还有2pc的第二阶段,如果某个节点迟迟不给回应。

4.1. 3pc的第一阶段:

在这里插入图片描述
如果3pc的第一个can commit,A节点和B节点收到TM的指令后,然后检查自己的程序,检查自己的sql,如果没问题。响应给TM,如果有一个节点检查返回的错误的信息。或者一个节点迟迟不给回应。那么这一阶段 就直接结束了

4.2. 3pc的第二阶段:

假如第一阶段,节点都返回ok。那么来到第二阶段
在这里插入图片描述
如果第二节点还是有一个节点,返回no,或者迟迟不回应,那么就直接回滚操作。

4.2. 3pc的第三阶段:

在这里插入图片描述
如果第三阶段。两个节点都是yes,那么咱们整个流程就走完了。如果在第三阶段有一个阶段迟迟没有给TM响应。那咱们的失联节点服务里面。就应该有判断自动提交的逻辑。为什么?(因为我们前两个阶段都是没有问题的。这样不就解决了2阶段的问题了么?)

五、TCC(Try Confirm Cancel)的方式:

其实tcc的方式,就是在操作最终一致性上面去添加日志信息。比如我们现在有个业务场景
张三给李四转账100,李四增加100,张三减100
在这里插入图片描述
具体Tcc的操作方式:

  1. 张三给李四进行转账100,张三扣减100,记录日志。李四增加100
  2. 如果李四增加的时候出现问题。根据记录的日志,给张三把那100元给恢复上。

相对于2PC、3PC、Tcc使用的范围量大,我们不止可以恢复mysql,更可以恢复redis等等。但是开发量大,业务代码量也大,我们每次执行必要的操作。都需要写相应恢复操作的代码。

阿里云的Seata就支持TCC这种模式。

六、Seata分布式事务框架入门:

官方的解释:

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

6.1 Seata AT模式

在这里插入图片描述
其实Seata和2PC模式非常相似,相对于2PC的模式下,Seata解决了数据库链接一直阻塞的问题。每个RM都执行完自己的事情后,直接释放掉数据库的链接了。而2PC的模式每个RM执行完了。必须等待TM发话确定提交还是回滚操作。

让我们分析下上面的这个图

  1. 首选第一步 TM申请一个全局锁
  2. RM向TC申请分支事务。RM申请本地锁,RM执行自己sql并且记录对应的unlog日志,RM提交本地事务。第一步拿不到全局锁,不能提交本地事务,只有当tm拿到全局锁,才能提交这个TM下面所有RM的事务。(防止出现脏读)写隔离
6.1.1写隔离

在这里插入图片描述
如果事务2的RM本地锁被占用着。那么事务1的第一个RM会等待事务2的本地锁进行释放。这个时候事务1拿到RM的本地锁并且全局锁,进行数据的回滚操作。

AT模式中,每个RM事务想commit or rollback 必须拥有本地锁和全局锁。

6.1.2读隔离

在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) 。
什么意思呢?
在这里插入图片描述

  1. 在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted)

这句话的意思就是:如果是上面的级别的话,在你进行修改和查询时,查询会被代理成 for update, for update这个事务就会去申请全局锁,直到事务1执行完,然后事务2获取到全局锁。继续执行其他的逻辑。

6.2 Seata TCC模式

TCC模式流程图:
在这里插入图片描述
下面我们模拟下TCC模式:
在这里插入图片描述
如果我们的业务逻辑变成下面这样会不会出现问题?
在这里插入图片描述
肯定会出现的。比如我们执行业务3的时候出现错误了。但是我的钱包已经扣减了100。张三也收到了100

假如这个瞬间,张三正好看手机了看到了收入100,然后业务3执行报错了,这个事务进行了rollback操作,张三又一看,钱又少了,这肯定不合理的。

我们可以改成这样:
在这里插入图片描述

这样我们就解决了张三这个问题了。这样就所有的RM都执行完。然后TM告诉TC,TC来告诉每个RM commit还是rollback。
这样张三没问题了。但是是不是我的钱包就会有问题?
我在某一刻看见我的钱包少了100,然后又加回来了。
在这里插入图片描述

这样是不是就解决了。我们上面两个脏读的问题了。

七、RocketmMQ事务消息

R

  1. 下单服务将半事务消息发送至 rockermq
  2. rockermq将消息持久化,向生产者返回ack确认消息已经发送成功,此时消息不投递,为半事务消息
    (如果rocketmq给我们回调半事务消息的时候,网络丢失了怎么办?
    rocketmq内部是有一个定时任务的,如果这次发给你了,你没有响应那就再隔一段时间又给你发一次。)
  3. 生产者开始执行本地事务逻辑
  4. 生产者根据本地事务执行结果,向mq发送commit或者 rollback,mq收到结果后处理逻辑如下:
    4.1 二次结果为 commit:服务端将半事务消息标记为可投递,并投递给消费者
    4.2 二次结果为 rollback:服务端将回滚事务,不会将半事务消息投递给消费者
    5.在断网或者是生产者应用重启的特殊情况下,若服务端未收到发送者提交的二次确认结果,或服务端收到的二次确认结果为Unknown未知状态,经过固定时间后,服务端将对消息生产者发起消息回查。
    6.mq会按照下单服务设置的参数,进行一系列的回查,超过次数后事务会强制回滚,
    7.mq收到消息会查结果后,执行最终结果。

大家如果仔细看了,上面的教程是不是觉得这个消息事务其实没啥用,
比如说,我们下单服务完了调用积分增减,只要保证我们下单服务能完成,然后再调用积分服务不就行了么?

让我们来看消费者来消费事务消息的流程:
在这里插入图片描述
这样就可以保证我们的分布式事务了,进入死信队列后,比如我们编写报警机制,然后保存到数据库,该人工补偿就人工补偿。至少比上面的方式,我们收到警告了,可以第一时间处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往日时光--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值