springCloud整合seata
Seata 作为分布式事务解决方案,致力于提供高性能简单易用的分布式服务。Seata提供了AT、TCC、SAGA、XA事务模式,此处介绍的是AT模式。
传统的单体应用中,通常本地数据库(@Transactional)保证一致性和完整性,而分布式环境中,多个服务进行跨数据库操作,此时本地事务无法保证全局事务一致性,这就需要引入分布式事务来协调多个服务之间的操作,保证分布式系统数据一致性和可靠性。
分布式事务通常以下三个角色组成:
1、事务协调者(Transaction Coordinator):简称TC,就是Seata服务端,负责协调并管理分布式事务的执行。他是分布式事务的协调器,协调多个参与者的事务操作。事务协调者负责全局事务的创建、提交、回滚以及事务的状态管理。简单理解就是,整个事务管理的老大。
2、事务管理器(Transaction Manager):简称TM,服务管理应用程序的本地事务(分支事务)。事务管理器定义了全局事务的范围。负责将分支事务注册到全局事务中,并在全局事务的协调下,执行本地事务的提交或者回滚。简单理解就是,执行整个分布式事务的每个小的本地事务单元(小弟)
3、资源管理器(Resource Manager): 简称RM,管理分支事务的资源,与TC交谈以注册分支事务和报告分支事务的状态。简单理解就是资源,比如mysql,Oracle、消息队列、redis等。此处使用mysql。
不说这些理论了,直接开始。
一、首先是下载并安装Seata和nacos.
下载地址为:https://github.com/seata/seata/releases。
这里的seata服务是注册到nacos上,所以还需要下载nacos,nacos下载地址:
https://github.com/alibaba/nacos/releases。下载解压后,进入到nacos目录,打开bin文件夹,windows使用命令:startup.cmd -m standalone 启动nacos单机模式。
二、在解压后的conf文件中找到application.yaml文件,参照application.example.yml文件。将相关连接信息改为你自己的,比如数据库连接改为你数据库的连接信息。
server: port: 7091 spring: application: name: seata-server logging: config: classpath:logback-spring.xml file: path: ${log.home:${user.home}/logs/seata} extend: logstash-appender: destination: 127.0.0.1:4560 kafka-appender: bootstrap-servers: 127.0.0.1:9092 topic: logback_to_logstash console: user: username: seata password: seata seata: config: # support: nacos 、 consul 、 apollo 、 zk 、 etcd3 type: nacos nacos: server-addr: 127.0.0.1:8848 #nacos地址 namespace: qiu #nacos上seataServer.properties所在命名空间 group: DEFAULT_GROUP #nacos上seataServer.properties所在分组group username: nacos #nacos账号 password: nacos #nacos密码 context-path: ##if use MSE Nacos with auth, mutex with username/password attribute #access-key: #secret-key: data-id: seataServer.properties #seata服务器端在nacos上的配置文件 registry: # support: nacos 、 eureka 、 redis 、 zk 、 consul 、 etcd3 、 sofa type: nacos #preferred-networks: 30.240.* nacos: application: seata-server #注册到seata上的服务名称 server-addr: 127.0.0.1:8848 #nacos地址 group: DEFAULT_GROUP #注册到nacos上分组 namespace: 4a00209c-f071-43eb-8ee0-30e929b6457a #注册到nacos所在命名空间 cluster: default #默认的即可 username: nacos #nacos账号 password: nacos #nacos密码 context-path: store: # support: file 、 db 、 redis 、 raft mode: db #数据库用db session: mode: db lock: mode: db db: datasource: druid db-type: mysql driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true #数据库连接地址 user: root #数据库账号 password: root #数据库密码 min-conn: 10 max-conn: 100 global-table: global_table branch-table: branch_table lock-table: lock_table distributed-lock-table: distributed_lock query-limit: 1000 max-wait: 5000 security: secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017 #不用去改变 tokenValidityInMilliseconds: 1800000 ignore: urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**
在nacos上建文件,名称为:seataServer.properties,内容如下:
store.mode=db store.lock.mode=db store.session.mode=db store.db.datasource=druid store.db.dbType=mysql store.db.driverClassName=com.mysql.cj.jdbc.Driver store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true # 数据库连接信息 store.db.user=root store.db.password=root store.db.minConn=5 store.db.maxConn=30 store.db.globalTable=global_table store.db.branchTable=branch_table store.db.distributedLockTable=distributed_lock store.db.queryLimit=100 store.db.lockTable=lock_table store.db.maxWait=5000
注意:这个文件所在的命名空间,会影响application.yaml里面的配置信息
三、采用的是AT模式,数据库需要做两个操作
1、需要建个数据库,名字最好是seata,并且在里面去初始化四张表,这四张表结构,在seata解压包里面的\script\server\db文件夹下,有个mysql.sql文件。将其放到Navicat中执行到seata数据库中
2、在需要执行的微服务数据库(比如我此处是user库和category库都要添加这张表)中需要初始化一张undo_log表。表结构如下
CREATE TABLE `undo_log` ( `id` bigint NOT NULL AUTO_INCREMENT, `branch_id` bigint NOT NULL, `xid` varchar(100) COLLATE utf8mb4_general_ci NOT NULL, `context` varchar(128) COLLATE utf8mb4_general_ci NOT NULL, `rollback_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `log_status` int NOT NULL, `log_created` datetime NOT NULL, `log_modified` date NOT NULL, `ext` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`), KEY `ux_undo_log` (`branch_id`,`xid`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLL
此处我把rollback_info字段类型改为varchar改为text,因为之前报过错误提示该字段长度不够。
四、启动seata服务端
打开seata解压文件夹,打开bin目录,双击seata-server.bat,启动成功后,访问http://localhost:7091/#/login ,能够看到下面页面说明seata服务端启动成功。
然后去nacos上看下seata服务是否已经注册上去,在你的seata的application.yaml中配置的nacos命名空间下找到seata-server,说明已经注册成功
五、seata客户端的使用配置
这里使用两个微服务模块,分别是catogory_mudule和user_module。只是个demo,微服务模块名称不必在乎
这两个微服务模块的配置信息:
1、添加依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
2、application.yaml配置信息如下:
seata: application-id: seata-demo-user registry: type: nacos nacos: server-addr: localhost:8848 #nacos地址 namespace: "4a00209c-f071-43eb-8ee0-30e929b6457a" #nacos上seata服务端所在命名空间 group: DEFAULT_GROUP #分组 application: seata-server #seata服务端服务名称 username: nacos password: nacos tx-service-group: seata_tx_group #这个通常使用默认的 service: vgroup-mapping: seata_tx_group: default data-source-proxy-mode: AT #AT模式
六、代码中添加注解@GlobalTransactional
@Override @GlobalTransactional public void testSeata(String username, String password, String deviceName) { // 当前服务数据 UserInfo info = new UserInfo(); info.setUserName(username); info.setPassword(password); boolean save = this.save(info); if (save){ log.info("用户信息保存成功"); } //int i = 1/0; Boolean device = categoryService.createDevice(deviceName); if (device){ log.info("保存设备信息成功"); } }
其中user为当前服务,category为远程调用category微服务模块,当然,此处你需要使用微服务调用组件feign或者openFeign。
另外好像我记得这个@GlobalTransactional只能加到serviceImpl层,不能添加到controller层,否则会失效。
结果:
如果此方法,两个微服务正常执行不报错,那么就提交事务保存到数据库
如果此方法发生错误,那么两个微服务的SQL都会进行回滚,数据库数据如旧。
保证了数据的可靠性和一致性。
相对而言,springcloud整合seata整体难度不大,但需要耐心点,配置好相关信息,基本都能正常使用。希望大家在学习和使用的路上一路顺风!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)