2026/2/9 8:43:14
网站建设
项目流程
怎么样做一个个人网站,软件app免费下载大全,程序员编程培训,网站制作加教程视频教程文章目录 前言5. Seata快速开始Seata Server(服务端)#xff08;TC#xff09;环境搭建下载安装包Server端存储模式#xff08;store.mode#xff09;支持三种#xff1a;创建数据库seata_server#xff0c;导入数据库文件修改application.yml文件修改config.txt文件修改…文章目录前言5. Seata快速开始Seata Server(服务端)TC环境搭建下载安装包Server端存储模式store.mode支持三种创建数据库seata_server导入数据库文件修改application.yml文件修改config.txt文件修改nacos-config.sh文件启动seata服务Seata Client(客户端)搭建创建undo_log表。引入pom文件引入配置文件启动项目查看是否连接成功6. 项目中的使用患者下单的service库存serviceapiapi实现查看是否回滚失败的原因前言如果你还对seata没有什么概念可以看我之前的文章 Seata1.7.0版本分布式事务介绍本篇接着上篇的讲解5. Seata快速开始https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html 官网文档Seata Server(服务端)TC环境搭建下载安装包https://github.com/seata/seata/releases 下载1.7.0版本Server端存储模式store.mode支持三种file(默认)单机模式全局事务会话信息内存中读写并持久化本地文件root.data性能较高(默认db5.7高可用模式全局事务会话信息通过db共享相应性能差些redis Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置我们这里使用db(数据库存储)所以接下来就去导入相关表创建数据库seata_server导入数据库文件打开seata\script\server\db文件夹下的mysql.sql文件。内容如下。-- -------------------------------- The script used when storeMode is db ---------------------------------- the table to store GlobalSession dataCREATETABLEIFNOTEXISTSglobal_table(xidVARCHAR(128)NOTNULL,transaction_idBIGINT,statusTINYINTNOTNULL,application_idVARCHAR(32),transaction_service_groupVARCHAR(32),transaction_nameVARCHAR(128),timeoutINT,begin_timeBIGINT,application_dataVARCHAR(2000),gmt_createDATETIME,gmt_modifiedDATETIME,PRIMARYKEY(xid),KEYidx_status_gmt_modified(status,gmt_modified),KEYidx_transaction_id(transaction_id))ENGINEInnoDBDEFAULTCHARSETutf8mb4;-- the table to store BranchSession dataCREATETABLEIFNOTEXISTSbranch_table(branch_idBIGINTNOTNULL,xidVARCHAR(128)NOTNULL,transaction_idBIGINT,resource_group_idVARCHAR(32),resource_idVARCHAR(256),branch_typeVARCHAR(8),statusTINYINT,client_idVARCHAR(64),application_dataVARCHAR(2000),gmt_createDATETIME(6),gmt_modifiedDATETIME(6),PRIMARYKEY(branch_id),KEYidx_xid(xid))ENGINEInnoDBDEFAULTCHARSETutf8mb4;-- the table to store lock dataCREATETABLEIFNOTEXISTSlock_table(row_keyVARCHAR(128)NOTNULL,xidVARCHAR(128),transaction_idBIGINT,branch_idBIGINTNOTNULL,resource_idVARCHAR(256),table_nameVARCHAR(32),pkVARCHAR(36),statusTINYINTNOTNULLDEFAULT0COMMENT0:locked ,1:rollbacking,gmt_createDATETIME,gmt_modifiedDATETIME,PRIMARYKEY(row_key),KEYidx_status(status),KEYidx_branch_id(branch_id),KEYidx_xid(xid))ENGINEInnoDBDEFAULTCHARSETutf8mb4;CREATETABLEIFNOTEXISTSdistributed_lock(lock_keyCHAR(20)NOTNULL,lock_valueVARCHAR(20)NOTNULL,expireBIGINT,primarykey(lock_key))ENGINEInnoDBDEFAULTCHARSETutf8mb4;INSERTINTOdistributed_lock(lock_key,lock_value,expire)VALUES(AsyncCommitting, ,0);INSERTINTOdistributed_lock(lock_key,lock_value,expire)VALUES(RetryCommitting, ,0);INSERTINTOdistributed_lock(lock_key,lock_value,expire)VALUES(RetryRollbacking, ,0);INSERTINTOdistributed_lock(lock_key,lock_value,expire)VALUES(TxTimeoutCheck, ,0);创建数据库seata_server注意数据库编码使用utf8mb4格式导入数据库文件修改application.yml文件修改D:\seata\seata\conf文件夹下的application.yml文件这个配置文件用于配置seata的注册中心配置中心以及事务相关的数据存储到哪里。# Copyright 1999-2019 Seata.io Group.## Licensed under the Apache License, Version 2.0 (the License);# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an AS IS BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.server:port:7091spring:application:name:seata-serverlogging:config:classpath:logback-spring.xmlfile:path:${user.home}/logs/seataextend:logstash-appender:destination:127.0.0.1:4560kafka-appender:bootstrap-servers:127.0.0.1:9092topic:logback_to_logstashconsole:user:username:seatapassword:seataseata:config:# support: nacos, consul, apollo, zk, etcd3# 这里配置的nacos的配置中心的位置type:nacosnacos:server-addr:127.0.0.1:8848namespace:group:SEATA_GROUPusername:nacospassword:nacosregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofa# 这里配置的nacos的注册中心的位置用于注册seata服务。type:nacosnacos:application:seata-serverserver-addr:127.0.0.1:8848group:SEATA_GROUPnamespace:cluster:defaultusername:nacospassword:nacosstore:# support: file 、 db 、 redis# 这里是使用数据库存储 事务相关的数据。mode:dbdb:datasource:druiddb-type:mysqldriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://127.0.0.1:3306/seata_server?rewriteBatchedStatementstrueuser:rootpassword:rootmin-conn:10max-conn:100global-table:global_tablebranch-table:branch_tablelock-table:lock_tabledistributed-lock-table:distributed_lockquery-limit:1000max-wait:5000# server:# service-port: 8091 #If not configured, the default is ${server.port} 1000security:secretKey:SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds:1800000ignore:urls:/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login修改config.txt文件打开文件D:\seata-server-1.7.0\seata\script\config-center 打开config.txt文件修改数据库连接信息store.db.dbTypemysql store.db.driverClassNamecom.mysql.cj.jdbc.Driver store.db.urljdbc:mysql://127.0.0.1:3306/seata_server?useUnicodetruerewriteBatchedStatementstruestore.db.userroot store.db.passwordroot修改nacos-config.sh文件修改D:\seata-server-1.7.0\seata\script\config-center\nacos下的 修改nacos-config.sh这份 Shell 脚本是 Seata 官方提供的 Nacos 配置自动初始化脚本核心作用是读取本地config.txt中的 Seata 配置项自动批量推送到 Nacos 配置中心避免手动在 Nacos 控制台逐个添加配置的繁琐操作。# 其他配置.........if[-z${host}];thenhostlocalhostfiif[-z${port}];thenport8848fiif[-z${group}];thengroupSEATA_GROUPfiif[-z${tenant}];thentenantfiif[-z${username}];thenusernamenacosfiif[-z${password}];thenpasswordnacosfi# 其他配置.........启动nacos后在去双击nacos-config.sh文件运行前提是必须安装git查看naocs配置信息能找到103条信息说明正确。启动seata服务在seata下的bin目录下启动seata-server.bat文件查看nacos注册中心看看是否被注册为服务。只要有seata-server就行Seata Client(客户端)搭建创建undo_log表。由上一章内容可知。客户端需要借助数据库中的undo_log表才能实现一阶段所以你需要在你要添加事务的业务模块所在表中添加undo_log表。举个例子你的要下订单并减库存假设你的下订单和减库存在一个叫做A的数据库就只需要在A这个数据库添加undo_log表。如果你的下订单和减库存分别在A数据库和B数据库中即分库了那么你需要分别在A和B数据库添加undo_log表。undo_log表结构如下。CREATETABLEundo_log(idbigint(20)NOTNULLAUTO_INCREMENT,branch_idbigint(20)NOTNULL,xidvarchar(100)NOTNULL,contextvarchar(128)NOTNULL,rollback_infolongblobNOTNULL,log_statusint(11)NOTNULL,log_createddatetimeNOTNULL,log_modifieddatetimeNOTNULL,PRIMARYKEY(id),UNIQUEKEYux_undo_log(xid,branch_id))ENGINEInnoDBAUTO_INCREMENT1DEFAULTCHARSETutf8;引入pom文件你需要在你需要事务的模块都引入seata。比如我有下单和库存两个微服务模块那么我就需要再两个微服务模块都引入这个包。dependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.7.0/version/dependency引入配置文件注意你需要在你需要事务的模块都引入seata配置文件。比如我有患者下单和库存两个微服务模块那么我就需要再两个微服务模块都写入这个配置文件。# Seata客户端配置seata:enabled:trueapplication-id:patient-server# 你当前模块在nacos注册中心的名字只有这里不同。tx-service-group:default_tx_group# 使用默认事务组 在你导入的103个配置文件中enable-auto-data-source-proxy:true#config:type:nacosnacos:server-addr:127.0.0.1:8848namespace:# public命名空间group:SEATA_GROUPusername:nacospassword:nacosregistry:type:nacosnacos:application:seata-serverserver-addr:127.0.0.1:8848namespace:# public命名空间group:SEATA_GROUPcluster:defaultusername:nacospassword:nacos启动项目查看是否连接成功在控制台按住CtrlF看看TMRM是否注册成功6. 项目中的使用上面我们已经在项目中导入了包并成功启动了患者下单的service我把我项目中一部分拿出来。ServicepublicclassPatientPayServiceImplimplementsPatientPayService{ResourceprivateMaterialInventoryApimaterialInventoryApi;// 调用库存模块的减库存操作ResourceprivateTreatmentRecordMappertreatmentRecordMapper;OverrideGlobalTransactional(namepatient-pay,rollbackForException.class)publicStringpatientPay(TreatmentRecordtreatmentRecord){// ...........// 更新订单状态intupdateCounttreatmentRecordMapper.updateById(updateRecord);if(updateCount0){System.err.println(更新支付状态失败recordIdtreatmentRecord.getRecordId());thrownewRuntimeException(更新支付状态失败);}// .........// 调用别的服务CommonResultIntegerresultmaterialInventoryApi.subtractMaterialInventory(item.getItemName(),item.getQuantity());if(result.getCode()!0||result.getData()0){System.err.println(扣减库存失败物品item.getItemName(), 数量item.getQuantity()接口返回result.getCode() - result.getMsg());// 主动抛出异常触发Seata回滚thrownewRuntimeException(库存扣减失败result.getMsg());}else{System.out.println(扣减库存成功物品item.getItemName(), 影响行数result.getData());}return支付成功;}}库存serviceapiFeignClient(namestoreroom)Tag(name操作物品库存接口)publicinterfaceMaterialInventoryApi{/** * 减物品库存 * param materialName 物资名称 * param count 减库存数量 * return 0表示失败, 1 表示成功 */PostMapping(/storeroom/inventory/subtractInventory)Operation(summary减物品库存)Parameters({Parameter(namematerialName,description物品名称,requiredtrue),Parameter(namecount,description数量,requiredtrue)})CommonResultIntegersubtractMaterialInventory(RequestParam(materialName)StringmaterialName,RequestParam(count)Integercount);}api实现RestControllerValidatedpublicclassMaterialInventoryApiImplimplementsMaterialInventoryApi{ResourceprivateInventoryInfoMapperinventoryInfoMapper;OverrideTransactionalTenantIgnore// 忽略租户PermitAll// 忽略登录/权限校验publicCommonResultIntegersubtractMaterialInventory(StringmaterialName,Integercount){inti1/0;// ....resultinventoryInfoMapper.subtractMaterialInventory(warehouseId,materialId,count);returnsuccess(result);}}查看是否回滚查看控制台CtrlF搜索查看undo_log表如果没有任何东西说明也回滚了。因为回滚成功seata会自动删除undo_log表的相关数据。失败的原因当使用全局异常处理器(比如RestControllerAdvice)时它会捕获Controller层抛出的所有异常并返回统一的响应格式。这会干扰Seata的异常传播机制。原理异常被拦截当库存服务抛出RuntimeException时RestControllerAdvice会捕获这个异常。返回正常响应异常处理器将异常转换为CommonResult等统一响应对象返回给调用方。Seata无法感知异常由于没有异常向上传播Seata的事务拦截器无法检测到异常因此不会触发回滚。需要手动判断您必须通过判断result.getCode() ! 0来手动抛出异常。