网站建设公司架构,网站备案 多ip,月刊可以用什么网站做,计算机网页设计是属于哪一个专业文章目录 一. Seata简介二. 官方文档三. Seata分布式事务代码实现0. 环境简介1. 添加undo_log表2. 添加依赖3. 添加配置4. 开启Seata事务管理5. 启动演示 四. Seata Server配置Nacos1. 修改配置类型2. 创建Nacos配置 五. Seata Client配置Nacos1. 增加Seata关联Nacos的配置2. 在… 文章目录 一. Seata简介二. 官方文档三. Seata分布式事务代码实现0. 环境简介1. 添加undo_log表2. 添加依赖3. 添加配置4. 开启Seata事务管理5. 启动演示 四. Seata Server配置Nacos1. 修改配置类型2. 创建Nacos配置 五. Seata Client配置Nacos1. 增加Seata关联Nacos的配置2. 在Nacos中对应的train-group添加配置3. 测试有效性 一. Seata简介
Seata 是一款开源的分布式事务解决方案旨在解决微服务架构下的数据一致性问题。它支持 AT、TCC、Saga 和 XA 四种事务模式能够适应不同的业务场景。
AT模式默认简单需要增加undo_log表生成反向SQL性能高回滚后原来没数据的现在还是没数据TCC模式try confirm/cancel三个阶段的代码都得自己实现Seata只负责调度对业务代码侵入性较强必要时可能还要修改数据库SAGA模式长事务解决方案需要程序员自己编写两阶段代码(AT模式不需要写第二阶段)基于状态机来实现的需要一个JSON文件可异步执行XA模式XA 协议是由 X/Open 组织提出的分布式事务处理规范基于数据库的XA协议来实现2PC发称为XA方案适用于强一致性的场景比如金融、银行等
Seata 的核心架构包括事务协调器TC、事务管理器TM和资源管理器RM通过两阶段提交协议实现全局事务的管理。其优势在于对业务代码侵入性低、性能高效且与 Spring Cloud、Dubbo 等主流微服务框架无缝集成是构建高可靠分布式系统的理想选择。
二. 官方文档
官方文档 下载地址 GitHub 仓库 Seata 示例项目
三. Seata分布式事务代码实现
接下来将用代码模拟AT模式的分布式事务管理。
0. 环境简介
项目模拟12306会员购票场景购票后需要进行余票更新以及会员购票信息保存的操作分别对应business模块和member模块的操作。要求business通过feign调用member的保存功能。
此时如果用传统事务注解Transactional仅仅在business模块的方法进行事务管理是无法管理远程调用的模块同样进行回滚的。
此时就要用到Seata进行分布式事务管理同时演示的是AT模式自动生成反向SQL。
1. 添加undo_log表
在business和member数据库中添加undo_log表执行SQL
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;2. 添加依赖
在business和member模块中添加Seata依赖 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactId/dependency3. 添加配置
在business和member模块的bootstrap.properties添加配置
# 事务组名称service.vgroupMapping.train-groupdefault
seata.tx-service-grouptrain-group
# 事务组和seata集群做关联
seata.service.vgroup-mapping.train-groupdefault
# seata集群对应的机器
seata.service.grouplist.default127.0.0.1:8091一个项目的多个模块配置成同一个事务组 4. 开启Seata事务管理
仅需要service业务逻辑方法上添加注解即可开启Seata事务管理
import io.seata.spring.annotation.GlobalTransactional;GlobalTransactional5. 启动演示
启动Seata服务 解压Seata文件夹双击bin目录下的seata-server.bat Seata服务可视化界面启动在7091端口而监听端口是8091 启动SpringBoot服务 可以看到启动后Seata打印的日志表明SpringBoot应用和Seata成功连接成功注册两个TM和RM 异常设置 为了显示事务回滚效果在member模块保存的业务逻辑中手动添加事务异常 public void save(MemberTicketReq req) throws Exception {LOG.info(seata全局事务ID save: {}, RootContext.getXID());DateTime now DateTime.now();Ticket ticket BeanUtil.copyProperties(req, Ticket.class);ticket.setId(SnowUtil.getSnowflakeNextId());ticket.setCreateTime(now);ticket.setUpdateTime(now);ticketMapper.insert(ticket);// 模拟被调用方出现异常if (1 1) {throw new Exception(测试异常11);}}预计效果为Seata回滚余票更新并向前端抛出异常 测试结果 与预期结果相同测试成功 四. Seata Server配置Nacos
让Nacos统一设置Seata Server的配置以免再去手动修改配置文件。 nacos的介绍和使用可以参考我之前的博客传送门 1. 修改配置类型
打开配置文件seata\conf\application.yml修改以下内容:
seata:config:# support: nacos, consul, apollo, zk, etcd3type: fileregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: file更改为nacos的注册中心和配置中心
seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 127.0.0.1:8848namespace: traingroup: SEATA_GROUPusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:data-id: seataServer.propertiesregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: traincluster: defaultusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:!!! 注意每个后面都要空一格 namespace: 设置nacos中的命名空间用于项目间隔离 groupnacos中分组名称 username和passwordnacos的用户名和密码默认都为nacos 重启Seata服务
可见配置已生效注册服务成功。登录Nacos客户端也可以看到配置的服务
2. 创建Nacos配置
创建本地数据库seata 在seata数据库中执行以下sql语句创建四张表
-- -------------------------------- The script used when storeMode is db --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS global_table
(xid VARCHAR(128) NOT NULL,transaction_id BIGINT,status TINYINT NOT NULL,application_id VARCHAR(32),transaction_service_group VARCHAR(32),transaction_name VARCHAR(128),timeout INT,begin_time BIGINT,application_data VARCHAR(2000),gmt_create DATETIME,gmt_modified DATETIME,PRIMARY KEY (xid),KEY idx_status_gmt_modified (status , gmt_modified),KEY idx_transaction_id (transaction_id)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS branch_table
(branch_id BIGINT NOT NULL,xid VARCHAR(128) NOT NULL,transaction_id BIGINT,resource_group_id VARCHAR(32),resource_id VARCHAR(256),branch_type VARCHAR(8),status TINYINT,client_id VARCHAR(64),application_data VARCHAR(2000),gmt_create DATETIME(6),gmt_modified DATETIME(6),PRIMARY KEY (branch_id),KEY idx_xid (xid)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS lock_table
(row_key VARCHAR(128) NOT NULL,xid VARCHAR(128),transaction_id BIGINT,branch_id BIGINT NOT NULL,resource_id VARCHAR(256),table_name VARCHAR(32),pk VARCHAR(36),status TINYINT NOT NULL DEFAULT 0 COMMENT 0:locked ,1:rollbacking,gmt_create DATETIME,gmt_modified DATETIME,PRIMARY KEY (row_key),KEY idx_status (status),KEY idx_branch_id (branch_id),KEY idx_xid (xid)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;CREATE TABLE IF NOT EXISTS distributed_lock
(lock_key CHAR(20) NOT NULL,lock_value VARCHAR(20) NOT NULL,expire BIGINT,primary key (lock_key)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (AsyncCommitting, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (RetryCommitting, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (RetryRollbacking, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (TxTimeoutCheck, , 0);新建配置如下
store.modedb
store.db.datasourcedruid
store.db.dbTypemysql
store.db.driverClassNamecom.mysql.cj.jdbc.Driver
store.db.urljdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatementstrue
store.db.userseata
store.db.passwordseata数据库、用户名和密码需要修改为自己的 这样就成功利用Nacos管理Seata的服务端配置了
五. Seata Client配置Nacos
接下来还需要用Nacos管理Seata的客户端配置。
1. 增加Seata关联Nacos的配置
在Seata管理的模块的bootstrap.properties中添加Nacos配置
# seata注册中心要和seata server的application.yml配置保持一致
seata.registry.typenacos
seata.registry.nacos.applicationseata-server
seata.registry.nacos.server-addr127.0.0.1:8848
seata.registry.nacos.groupSEATA_GROUP
seata.registry.nacos.namespacetrain
seata.registry.nacos.usernamenacos
seata.registry.nacos.passwordnacos# seata配置中心要和seata server的application.yml配置保持一致
seata.config.typenacos
seata.config.nacos.server-addr127.0.0.1:8848
seata.config.nacos.groupSEATA_GROUP
seata.config.nacos.namespacetrain
seata.config.nacos.dataIdseataServer.properties
seata.config.nacos.usernamenacos
seata.config.nacos.passwordnacos# 事务组名称必须在nacos中有配置过service.vgroupMapping.train-groupdefault
seata.tx-service-grouptrain-group2. 在Nacos中对应的train-group添加配置 service.vgroupMapping.train-groupdefault
service.default.grouplist127.0.0.1:8091解释 原来这两行是在SpringBoot中配置的而现在配置了SeataNacos等于是Nacos统一管理配置了不用在本地一处处修改了只要在线上统一管理即可。而在本地仅需要配置事务组名称即可简化了配置。 3. 测试有效性
还是手动抛出异常查看是否回滚 成功回滚则线上配置生效