从seata的最简单模式file模式开始,学习下seata。开始之前先启动下seata TC,启动脚本如下:
version: "3"services:seata-server:image: seataio/seata-server:latesthostname: seata-serverports:- "8091:8091"- "7091:7091"environment:- SEATA_PORT=8091- STORE_MODE=file- SEATA_CONFIG_NAME=file:/root/seata-config/registry
看到server started说明启动成功了
% docker compose -f ./learn/seata/exp1/docker-compose.yaml upWARN[0000] Found orphan containers ([exp1_benthos_1 exp1_app_1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.[+] Running 1/1⠿ Container exp1-seata-server-1 Created 0.3sAttaching to exp1-seata-server-1exp1-seata-server-1 | apm-skywalking not enabledexp1-seata-server-1 | Affected JVM parameters: -Dlog.home=/root/logs/seata -server -Dloader.path=/lib -Xmx2048m -Xms2048m -Xss640k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/root/logs/seata/java_heapdump.hprof -XX:+DisableExplicitGC -Xloggc:/root/logs/seata/seata_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -Dio.netty.leakDetectionLevel=advanced -Dapp.name=seata-server -Dapp.pid=1 -Dapp.home=/ -Dbasedir=/exp1-seata-server-1 | OpenJDK 64-Bit Server VM warning: Cannot open file root/logs/seata/seata_gc.log due to No such file or directoryexp1-seata-server-1 |exp1-seata-server-1 | ███████╗███████╗ █████╗ ████████╗ █████╗exp1-seata-server-1 | ██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔══██╗exp1-seata-server-1 | ███████╗█████╗ ███████║ ██║ ███████║exp1-seata-server-1 | ╚════██║██╔══╝ ██╔══██║ ██║ ██╔══██║exp1-seata-server-1 | ███████║███████╗██║ ██║ ██║ ██║ ██║exp1-seata-server-1 | ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝exp1-seata-server-1 |exp1-seata-server-1 |exp1-seata-server-1 | 15:06:52.305 INFO --- [ main] [ta.config.ConfigurationFactory] [ load] [] : load Configuration from :Spring Configurationexp1-seata-server-1 | 15:06:52.398 INFO --- [ main] [ta.config.ConfigurationFactory] [ buildConfiguration] [] : load Configuration from :Spring Configurationexp1-seata-server-1 | 15:06:53.580 INFO --- [ main] [seata.server.ServerApplication] [ logStarting] [] : Starting ServerApplication using Java 1.8.0_342 on seata-server with PID 1 (/seata-server/classes started by root in seata-server)exp1-seata-server-1 | 15:06:53.585 INFO --- [ main]exp1-seata-server-1 | 15:07:02.862 INFO --- [ main] [io.seata.server.ServerRunner ] [ run] [] : seata server started in 1035 millSeconds
seata-examples里面的api,实现了官方最简单的例子

我们开始一步步实现它:首先启动mysql
% docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.72023-09-16 14:47:41+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.40-1.el7 started.2023-09-16 14:47:41+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
然后创建对应的几个表
% mysql -uroot -p123456 -h127.0.0.1mysql> create database fescar;Query OK, 1 row affected (0.03 sec)mysql> use fescar;Database changedmysql> CREATE TABLE `account_tbl`(`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` varchar(255) DEFAULT NULL,`money` int(11) DEFAULT '0',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;CREATE TABLE `stock_tbl`(`id` int(11) NOT NULL AUTO_INCREMENT,`commodity_code` varchar(255) DEFAULT NULL,`count` int(11) DEFAULT '0',PRIMARY KEY (`id`),UNIQUE KEY `commodity_code` (`commodity_code`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;CREATE TABLE `order_tbl`(`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` varchar(255) DEFAULT NULL,`commodity_code` varchar(255) DEFAULT NULL,`count` int(11) DEFAULT '0',`money` int(11) DEFAULT '0',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;mysql> 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`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;Query OK, 0 rows affected (0.02 sec)
找到目录seata-example/seata-samples/api/pom.xml修改下slf4j版本
<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.1</version><scope>provided</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>2.0.9</version></dependency>
接着修改下配置文件src/main/resources/jdbc.properties
jdbc.account.url=jdbc:mysql://127.0.0.1:3306/fescar?useSSL=false&serverTimezone=UTCjdbc.account.username=rootjdbc.account.password=123456jdbc.account.driver=com.mysql.jdbc.Driver# stock db configjdbc.stock.url=jdbc:mysql://127.0.0.1:3306/fescar?useSSL=false&serverTimezone=UTCjdbc.stock.username=rootjdbc.stock.password=123456jdbc.stock.driver=com.mysql.jdbc.Driver# order db configjdbc.order.url=jdbc:mysql://127.0.0.1:3306/fescar?useSSL=false&serverTimezone=UTCjdbc.order.username=rootjdbc.order.password=123456jdbc.order.driver=com.mysql.jdbc.Driver
然后编译
mvn build && mvn install
执行下
% java --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.net.util=ALL-UNNAMED -jar target/seata-samples-api-1.1.0.jarC00321SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".SLF4J: Defaulting to no-operation MDCAdapter implementation.SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.begin trx, xid is 172.23.0.2:8091:18450265429737473rollback trx, cause: data negative, xid is 172.23.0.2:8091:18450265429737473
事务回滚了,查询下数据库,money和stock都是初始值,说明实现了一致性。因为单价是200,买5个的话账户余额不足。
mysql> select * from order_tbl;Empty set (0.00 sec)mysql> select * from account_tbl;+----+---------+-------+| id | user_id | money |+----+---------+-------+| 2 | U100001 | 999 |+----+---------+-------+1 row in set (0.00 sec)mysql> select * from stock_tbl;+----+----------------+-------+| id | commodity_code | count |+----+----------------+-------+| 2 | C00321 | 100 |+----+----------------+-------+1 row in set (0.00 sec)
我们把数量改成4,测试下
% java --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.net.util=ALL-UNNAMED -jar target/seata-samples-api-1.1.0.jarC00321SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".SLF4J: Defaulting to no-operation MDCAdapter implementation.SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.begin trx, xid is 172.23.0.2:8091:1845026542973749396199true
事务执行成功了,并且数据库也符合我们的预期
mysql> select * from stock_tbl;+----+----------------+-------+| id | commodity_code | count |+----+----------------+-------+| 6 | C00321 | 96 |+----+----------------+-------+1 row in set (0.00 sec)mysql> select * from order_tbl;+----+---------+----------------+-------+-------+| id | user_id | commodity_code | count | money |+----+---------+----------------+-------+-------+| 6 | U100001 | C00321 | 4 | 800 |+----+---------+----------------+-------+-------+1 row in set (0.00 sec)mysql> select * from account_tbl;+----+---------+-------+| id | user_id | money |+----+---------+-------+| 6 | U100001 | 199 |+----+---------+-------+1 row in set (0.00 sec)
至此,我们体验完了最简单的文件模式。
文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




