Seata1.3(AT模式) + Zookeeper +Dubbo

tech2025-05-18  14

Seata1.3(AT模式) + Zookeeper +Dubbo 整合

Seata下载

注:AT模式

我下载的是源码

建立数据库 SEATA ,AT 模式需要 UNDO_LOG 表;每个和业务相关的库都要有一张 UNDO_LOG 表,后续打断点调试,能看到里面的暂存数据 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for branch_table -- ---------------------------- DROP TABLE IF EXISTS `branch_table`; CREATE TABLE `branch_table` ( `branch_id` bigint(20) NOT NULL, `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `transaction_id` bigint(20) NULL DEFAULT NULL, `resource_group_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `lock_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `branch_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `status` tinyint(4) NULL DEFAULT NULL, `client_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `gmt_create` datetime(0) NULL DEFAULT NULL, `gmt_modified` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`branch_id`) USING BTREE, INDEX `idx_xid`(`xid`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for global_table -- ---------------------------- DROP TABLE IF EXISTS `global_table`; CREATE TABLE `global_table` ( `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `transaction_id` bigint(20) NULL DEFAULT NULL, `status` tinyint(4) NOT NULL, `application_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `transaction_service_group` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `transaction_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `timeout` int(11) NULL DEFAULT NULL, `begin_time` bigint(20) NULL DEFAULT NULL, `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `gmt_create` datetime(0) NULL DEFAULT NULL, `gmt_modified` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`xid`) USING BTREE, INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE, INDEX `idx_transaction_id`(`transaction_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for lock_table -- ---------------------------- DROP TABLE IF EXISTS `lock_table`; CREATE TABLE `lock_table` ( `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `transaction_id` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `branch_id` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pk` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `gmt_create` datetime(0) NULL DEFAULT NULL, `gmt_modified` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`row_key`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for undo_log -- ---------------------------- DROP TABLE IF EXISTS `undo_log`; CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(11) NOT NULL, `log_created` datetime(0) NOT NULL, `log_modified` datetime(0) NOT NULL, `ext` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;

源码导入idea 报错: io.seata.codec.protobuf.generated不存在 ! 解决方案:本地执行 ./mvnw clean install -DskipTests=true (Mac,Linux) 或 mvnw.cmd clean install -DskipTests=true (Win) 这个官网有讲到!!!!

修改script/config-center/下的 config.txt 文件 主要修改 store.mode=db 以及数据库的连接信息 下边这行代码是重点 service.vgroupMapping.doushanglai-service_tx_group=default 旧版本是vgroup_mapping,新版本是 vgroupMapping 如果看的帖子太多,配置文件新老掺和在一起的话要注意

config.txt

transport.type=TCP transport.server=NIO transport.heartbeat=true transport.enableClientBatchSendRequest=false transport.threadFactory.bossThreadPrefix=NettyBoss transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler transport.threadFactory.shareBossWorker=false transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector transport.threadFactory.clientSelectorThreadSize=1 transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread transport.threadFactory.bossThreadSize=1 transport.threadFactory.workerThreadSize=default transport.shutdown.wait=3 service.vgroupMapping.doushanglai-service_tx_group=default service.default.grouplist=127.0.0.1:8091 service.enableDegrade=false service.disableGlobalTransaction=false client.rm.asyncCommitBufferLimit=10000 client.rm.lock.retryInterval=10 client.rm.lock.retryTimes=30 client.rm.lock.retryPolicyBranchRollbackOnConflict=true client.rm.reportRetryCount=5 client.rm.tableMetaCheckEnable=false client.rm.sqlParserType=druid client.rm.reportSuccessEnable=false client.rm.sagaBranchRegisterEnable=false client.tm.commitRetryCount=5 client.tm.rollbackRetryCount=5 client.tm.degradeCheck=false client.tm.degradeCheckAllowTimes=10 client.tm.degradeCheckPeriod=2000 store.mode=db store.file.dir=file_store/data store.file.maxBranchSessionSize=16384 store.file.maxGlobalSessionSize=512 store.file.fileWriteBufferCacheSize=16384 store.file.flushDiskMode=async store.file.sessionReloadReadSize=100 store.db.datasource=hikari store.db.dbType=mysql store.db.driverClassName=com.mysql.jdbc.Driver store.db.url=jdbc:mysql://192.168.0.162:3306/seata?useUnicode=true store.db.user=seata store.db.password=&Seata12 store.db.minConn=5 store.db.maxConn=30 store.db.globalTable=global_table store.db.branchTable=branch_table store.db.queryLimit=100 store.db.lockTable=lock_table store.db.maxWait=5000 store.redis.host=127.0.0.1 store.redis.port=6379 store.redis.maxConn=10 store.redis.minConn=1 store.redis.database=0 store.redis.password=null store.redis.queryLimit=100 server.recovery.committingRetryPeriod=1000 server.recovery.asynCommittingRetryPeriod=1000 server.recovery.rollbackingRetryPeriod=1000 server.recovery.timeoutRetryPeriod=1000 server.maxCommitRetryTimeout=-1 server.maxRollbackRetryTimeout=-1 server.rollbackRetryTimeoutUnlockEnable=false client.undo.dataValidation=true client.undo.logSerialization=jackson client.undo.onlyCareUpdateColumns=true server.undo.logSaveDays=7 server.undo.logDeletePeriod=86400000 client.undo.logTable=undo_log client.log.exceptionRate=100 transport.serialization=seata transport.compressor=none metrics.enabled=false metrics.registryType=compact metrics.exporterList=prometheus metrics.exporterPrometheusPort=9898 启动注册中心,把seata 配置写入到注册中心 如果你本地的注册中心用的nacos,在seata项目下的script/ config-center/ 下 执行脚本。 sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca -u username - w password

这一步是把seata 的配置写进注册中心,项目此模块下的 md文档上有写。 nacos的话应该按照文档来, 一套流程走到底。

重点本人用的 Zk,同样执行上边的脚本命令

zk-config.sh -h localhost -p 2181 -z "/Users/zhangchenghui/zookeeper-3.4.14

这个脚本命令执行后,在Zk的节点上只看到了 /seata 节点,下边的子节点全是空的。 所以怀疑1.3 的zk.sh 脚本有问题,仅仅是怀疑,也可能是我自己没搞好,解决方案,代码如下:

代码写入 seata 节点(拷贝别人的)

import com.google.common.base.Charsets; import org.I0Itec.zkclient.ZkClient; import org.I0Itec.zkclient.exception.ZkMarshallingError; import org.I0Itec.zkclient.serialize.ZkSerializer; import org.apache.zookeeper.CreateMode; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.Set; public class ZkDataInit { private static volatile ZkClient zkClient; public static void main(String[] args) { if (zkClient == null) { zkClient = new ZkClient("127.0.0.1:2181", 6000, 2000); zkClient.setZkSerializer(new ZkSerializer() { @Override public byte[] serialize(Object o) throws ZkMarshallingError { return String.valueOf(o).getBytes(Charsets.UTF_8); } @Override public Object deserialize(byte[] bytes) throws ZkMarshallingError { return new String(bytes, Charsets.UTF_8); } }); } if (!zkClient.exists("/seata")) { zkClient.createPersistent("/seata", true); } //获取key对应的value值 Properties properties = new Properties(); // 使用ClassLoader加载properties配置文件生成对应的输入流 // 使用properties对象加载输入流 try { File file=new File("C:\\Users\\zjj\\Desktop\\seata-1.3.0\\script\\config-center\\config.txt"); InputStream in = new FileInputStream(file); properties.load(in); Set<Object> keys = properties.keySet(); for (Object key : keys) { putConfig(key.toString(), properties.get(key).toString()); } } catch (IOException e) { e.printStackTrace(); } } /** * @param dataId * @param content * @return */ public static boolean putConfig(final String dataId, final String content) { Boolean flag = false; String path = "/seata/" + dataId; if (!zkClient.exists(path)) { zkClient.create(path, content, CreateMode.PERSISTENT); flag = true; } else { zkClient.writeData(path, content); flag = true; } return flag; }

运行完之后,查看zk的 /seata 节点下是否有子节点,如图所示就对了

修改seata-server 下的 file.conf 和 registry.conf 主要修改mode以及数据库连接信息和注册方式

file.conf

## transaction log store, only used in seata-server store { ## store mode: file、db、redis mode = "db" ## database store property db { datasource = "hikari" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" driverClassName = "com.mysql.jdbc.Driver" url = "jdbc:mysql://192.168.0.162:3306/seata" user = "seata" password = "&Seata12" minConn = 5 maxConn = 30 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } }

registry.conf

registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "zk" zk { cluster = "default" serverAddr = "127.0.0.1:2181" sessionTimeout = 60000 connectTimeout = 20000 username = "" password = "" } file { name = "file.conf" } } config { # file、nacos 、apollo、zk、consul、etcd3 type = "zk" zk { serverAddr = "127.0.0.1:2181" sessionTimeout = 60000 connectTimeout = 20000 username = "" password = "" } file { name = "file.conf" } } 以上确保配置没有问题,启动Server main() 直接启动 如果有一连串的getconfig 错误 检查 注册中心节点是否配置成功项目配置

springboot配置

seata: enabled: true application-id: ${spring.application.name} tx-service-group: doushanglai-service_tx_group enable-auto-data-source-proxy: true config: type: zk zk: serverAddr: 127.0.0.1:2181 registry: type: zk zk: application: ${spring.application.name} server-addr: 127.0.0.1:2181

启动dubbo A服务 和 B服务

测试代码如下

@Override @GlobalTransactional(rollbackFor = Exception.class) public JsonResult test() { System.out.println("开始全部事务============================》"); goodsService.test(); LambdaUpdateWrapper<Task> l = Wrappers.lambdaUpdate(); Task t = new Task(); t.setGoodsId(999L); this.baseMapper.update(t, l); throw new RuntimeException("测试报错"); } @Override public JsonResult test() { System.out.println("进入商品TEST事务之前=======================================》》》"); LambdaUpdateWrapper<Goods> u = Wrappers.lambdaUpdate(); Goods g = new Goods(); g.setStock("200"); this.baseMapper.update(g, u); System.out.println("进入商品TEST事务之后=======================================》》》"); return null; } @PostMapping("test") @ApiOperation(value = "测试分布式事务【A调用B,A抛异常,AB数据都回滚】", notes = "测试分布式事务【A调用B,A抛异常,AB数据都回滚】", produces = "application/json") public JsonResult detailAuthFeeList() { return JsonResult.buildResult(taskService.test()); }

结果A服务 Log

B服务 Log

数据库数据 goods表

Task表

可以在调用端打断点,观察数据库表数据的变化,还有seata 几张表的数据变化,这样更容易理解点。

初步使用已经成功,还在更深入的了解中

配置参考:官方教学

总结:

注册中心的seata配置要确定没问题,才能往下继续进行,其他注册中心没试过,seata 源码zookeeper 的写配置的脚本一直写不成功config.txt 里 service.vgroupMapping.doushanglai-service_tx_group=default 的 doushanglai-service_tx_group 配置啥样的 项目对应的服务配置就要写成啥样,修改完config.text的内容后要重新把节点写入一下注册中心(zk,其他注册中心不是很清楚)seata no available service ‘null’ found, please make sure registry config correct 这个错误检查 上边的service.vgroupMapping.doushanglai-service_tx_group=default 是否正确,是否能在注册中心的节点上找到项目结构不一样,所以仅供参考
最新回复(0)