目录
1、分布式事务特点
1.1、分布式事务是什么
1.2、分布式事务产生的场景
2、使用seata解决分布式事务
2.1、认识seata
2.1.1、seata是什么
2.1.2、seata三大角色
2.1.3、seata模式
2.1.3.1、AT模式
AT模式实现:
2.2、如何使用seata
3、seata基于idea软件开发
1、分布式事务特点
1.1、分布式事务是什么
分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。
那分布式事务和普通数据库的事务的区别是什么?
我们知道本地事务依赖数据库本身提供的事务特性来实现,因此以下逻辑可以控制本地事务:
begin transaction;
//1.本地数据库操作:我减少金额
//2.本地数据库操作:你增加金额
commit transation;
但是在分布式环境下,会变成下边这样:
begin transaction;
//1.本地数据库操作:我减少金额
//2.远程调用:让你增加金额
commit transation;
所以说我们就可以把他理解为是基于远程调用的数据库事务
1.2、分布式事务产生的场景
1、典型的场景就是微服务架构微服务之间通过远程调用完成事务操作。 比如:订单微服务和库存微服务,下单的同时订单微服务请求库存微服务减库存。 简言之:跨JVM进程产生分布式事务。
2、单体系统访问多个数据库实例 当单体系统需要访问多个数据库(实例)时就会产生分布式事务。 比如:用户信息和订单信息分别在两个MySQL实例存储,用户管理系统删除用户信息,需要分别删除用户信息及用户的订单信息,由于数据分布在不同的数据实例,需要通过不同的数据库链接去操作数据,此时产生分布式事务。 简言之:跨数据库实例产生分布式事务。
3、多服务访问同一个数据库实例 比如:订单微服务和库存微服务即使访问同一个数据库也会产生分布式事务,原因就是跨JVM进程,两个微服务持有了不同的数据库链接进行数据库操作,此时产生分布式事务。
2、使用seata解决分布式事务
2.1、认识seata
解决分布式事务的方案有很多,但实现起来都比较复杂,因此我们一般会使用开源的框架来解决分布式事务问题。在众多的开源分布式事务框架中,功能最完善、使用最多的就是阿里巴巴在2019年开源的Seata了。
2.1.1、seata是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)。
2.1.2、seata三大角色
在 Seata 的架构中,一共有三个角色:
- TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态
并驱动分支事务提交或回滚
2.1.3、seata模式
Seata支持四种不同的分布式事务解决方案:
-
XA
-
TCC
-
AT
-
SAGA
这里我们以AT
模式来给大家讲解其实现原理。
2.1.3.1、AT模式
AT 模式是一种无侵入
的分布式事务解决方案。阿里 Seata
框架,实现了该模式。
在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。
AT模式实现:
一阶段:Seata 会拦截" 业务SQL",解析 SQL 语义
查询 “业务SQL” 要更新的业务数据,在业务数据被更新前,将其保存成 “before image”
执行 “业务SQL” ,更新业务数据
查询更新后的数据,将其保存成 “after image”
将 before image 和 after image 保存至 Undo Log 表中
生成行锁
以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
二阶段(提交):
因为 “业务SQL” 在一阶段已经提交至数据库,所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
二阶段(回滚):
首先要校验脏写,对比“数据库当前业务数据”和 “after image”
如果两份数据完全一致就说明没有脏写,可以还原业务数据。
如果不一致就说明有脏写,出现脏写就需要转人工处理。
用“before image”还原业务数据
删除快照数据和行锁
2.2、如何使用seata
两种方式:
- 一种是基于虚拟机安装
- 一种是基于Windows安装
以下的安装都是基于虚拟机安装的,如果没有虚拟机但是想使用虚拟机操作seata
可以翻看作者以前的作品docker容器的安装以及用法_docker容器的安装和使用-CSDN博客
这里面有虚拟机安装的教程
如果只想从windows系统中操作的话,也可以查看这位作者:Windows 下载安装 Seata_seata下载-CSDN博客
首先打开虚拟机,并且启动docker
将文档所带上的压缩包解压并且放在虚拟机中,执行ls命令,可以进行查看文件夹是否存在
cd seata 进入这个文件夹
再执行命令修改这个文件夹
一般情况下,只需要修改这一段的MySQL配置就可以了,因为其他的都是默认的
然后直接执行这段语句,安装seata就可以了
docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.87.99 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network hmall \
-d \
seataio/seata-server:1.5.2
但是其中的IP地址需要改成自己的,network网络配置需要改成自己的
如果没有网络的话,直接删掉这一行就可以了
执行上面那句后,就可以启动seata,如果没有问题,代表启动成功了
然后就可以查看一下他的信息
docker start seata
docker ps
这样可以正常的看到信息,代表我们安装成功了
3、seata基于idea软件开发
在nacos中添加一个共享的seata,命名为shared-seata.yaml
seata:registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址type: nacos # 注册中心类型 nacosnacos:server-addr: 192.168.87.99:8848 # nacos地址namespace: "" # namespace,默认为空group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUPapplication: seata-server # seata服务名称username: nacospassword: nacostx-service-group: hmall # 事务组名称service:vgroup-mapping: # 事务组与tc集群的映射关系hmall: "default"data-source-proxy-mode: AT
添加上面这些配置即可
CREATE TABLE `undo_log` (`branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',`xid` varchar(128) NOT NULL COMMENT 'global transaction id',`context` varchar(128) NOT NULL COMMENT 'undo_log context,such as serialization',`rollback_info` longblob NOT NULL COMMENT 'rollback info',`log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',`log_created` datetime(6) NOT NULL COMMENT 'create datetime',`log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AT transaction mode undo table';
在数据库中执行该语句,添加一个新的表,在每个需要使用seata的地方都需要添加此表
在idea中需要导入依赖,在所需要使用seata的地方引入以下依赖即可
<!--统一配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--读取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency>
还需要创建一个bootstrap.yml,是为了用来连接nacos的
spring:application:name: trade-service # 服务名称profiles:active: devcloud:nacos:server-addr: 192.168.87.99 # nacos地址config:file-extension: yaml # 文件后缀名shared-configs: # 共享配置- dataId: shared-seata.yaml # 共享seata配置
最后就到了测试分布式事务的时候到了
将之前有@Transactional注解的地方改成@GlobalTransactional
最后如果执行一个错误的东西,但是不能成功,并且数据还是原来的样子
这样就表示我们的基于seata的分布式事务成功了