赞
踩
分布式事务:简单理解就是一个业务需要调用多个远程微服务操作数据库所产生的问题。
本地事务:单个服务对自己本身的数据库所做的操作(增删改)。
事务的四大特性(ACID)
如果在一个业务中对一个数据库进行增加和删除操作,必须保证增加和删除操作同时成功或者同时失败
操作后的数据总和不变;例如:转账,小明有200,小花有100,小明给小花转了100,小明100,小花200;那么无论怎么转,必须得保证数据的总和是300;也类似与原子性(能量守恒定律)
多个事务同时执行时,一个事务的执行不应影响其他事务的执行;类似于加锁,一个线程进去了,其它线程想要进去需要排队等候
完成的事务会永久的保存在数据库中,实现永久存储,事务执行完,此操作不可以回滚;比如:想数据库中添加一条数据,如果该业务正常提交,那么在提交的一瞬间,数据就实现的永久化的存储,且该事务不可逆;
首先了解一下分布式相关的理论:
分布式系统的三个指标,也就是分布式系统需要做到的事情:
注意:这三个指标不可能同时做到,只能满足其中两点
分区容错性:
服务于服务之间存放的地址(位置)是不一样的,所以两个服务之间的调用不可能保证一定成功,总会存在失败;例如:网络抖动,调用超时等等;所以该指标P必须成立,剩下的就只能在C和A选一个了
一致性(强一致性):
场景:有一个客户端A,一个服务端B和一个服务端C(两服务之间数据需同步)B和C服务中有一个数据key=小王;
A对B服务发起修改操作,将key修改成老王;A又对C服务发起查询key的操作,在查询的时候如果B的数据还没有同步到C中,遇到了网络抖动或者超时原因,那么会处于等待状态,等同步完成了才会将key的值返回。也就是说无论如何,拿到的数据都将是最新的
可用性:
例如上一个例子,如果数据B在同步数据到C时,如果出现网络抖动或者超时,不会等待数据同步,会直接将key=小王的值返回给A客服端。
也就是说,只需要能返回结果数据就可以,可以不用保证数据的一致性
总之,两个服务之间的调用无法同时满足一致性与可用性;如果选择了一致性必将放弃服务的可用性;如果选择了可用性也就意味着放弃了一致性。
所以只有两个可能性:AP或CP
BASE:全称:Basically Available(基本可用),Soft state(软状态),和 Eventually consisten(最终一致性)三个短语的缩写,来自 ebay 的架构师提出。BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于 CAP 定理逐步演化而来的。其核心思想是:
1.Basically Available(基本可用)
也就是说如果系统出现了故障,依然还是可以用
2.Soft state(软状态)
相对的就有一个硬状态
硬状态:例如在一个集群中(服务器存放的数据是一样的),服务器之间必须做到数据的统一,也就是会保证服务器数据的一致性。
软状态:也是例如在一个集群中,允许服务器中的数据存在中间状态,也就是说,服务器之间的数据可以不用做到一致性;例如:向集群的服务器A修改一条数据,那么如果集群中的服务器B因为某些原因不能同步修改后的数据,那么它还是会保持原来未修改的数据。
3.Eventually consistent(最终一致性)
系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态
还是例如在一个集群中,向A服务更新数据,B服务器可能因为某些原因不会及时同步,但是,无论经过多长时间,最终总会实现数据的同步也就是最终一致性。
XA规范中的分布式事务由AP、RM、TM组成
AP:应用程序(可以理解成是一个完整的程序)
RM:资源管理器(参与了分布式事务的服务)
TM:事务管理器(管理所有参与了分布式事务的服务)
微服务举例场景:
服务器A添加一条数据时,同时也需要向服务器B和C也添加一条数据(分布式场景下)
二阶段协议:
第一阶段:
例如上面的场景:AP属于的是整个项目的总称;服务器A、B、C都属于RM,TM是独立出来的,用于管理RM
一开始,TM会要求所有的RM准备提交对应的事务分支,也就是要服务器A、B、C告诉TM,自己本身对数据的操作能不能进行提交(大白话的说,就是你能不能办事),如果能提交就返回ok给TM,不能就返回no给TM,如果有一个RM发送了no,那么它就需要将自己的事务进行回滚,并丢弃该事务分支。
第二阶段:
TM会根据所有的RM返回的结果决定是提交还是回滚(ok:提交 no:回滚),如果决定提交,那么TM会通知所有的RM进行提交;如果决定回滚那么TM会通知所有的RM回滚自己的事务分支
总结
优点:很好的保证了数据的强一致性,适合对数据强一致性高的场景(并不能保证100%强一致)
缺点:实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景。
TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
例如: A要向 B 转账,思路大概是:
我们有一个本地方法,里面依次调用:
1、首先在 Try 阶段,要先调用远程接口把 B和 A的钱给冻结起来。
2、在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
3、如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。
优点: 相比两阶段提交,可用性比较强
缺点: 数据的一致性要差一些。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。
使用RocketMQ实现
版本为4.3以上,因为4.3以上的版本才支持事务消息
SeataAT模式中的角色:
场景:在使用微服务架构的新闻类app中,有一业务:用户认证,即普通用户申请成为自媒体用户,如果审核通过,在用户服务中,会向自媒体服务以及作者服务的数据库中都添加一条该用户的数据,以此说明该用户确实成为了自媒体人。而这个业务中涉及到了三个微服务,且都需要在各自的服务中的数据库添加一条数据。那么就产生了分布式事务的问题。解决如下:
使用Seata解决很简单,在servic中实现该业务的方法上添加@GlobalTransactional注解。
Seata具体实现流程分为两个阶段:
一阶段:
二阶段:
会产生的问题:脏读脏写
原因:
在第一阶段中,数据库中的数据在还没有真正决定是提交还是回滚的情况下,数据已经真正修改了,那么如果在这个时候,有个业务去访问你刚添加的数据他是可以访问的。但其实你能访问的。一但最终结果是回滚,那么数据是需要回滚的。所以会产生数据的脏读现象。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。