本篇文章是从Seata官方样例改造而来的分布式事务,Nacos为服务的注册中心及配置中心,这里我采用的组件的版本为:Nacos 2.1.0、Seata 1.5.2
Seata的官方样例库为:https://github.com/seata/seata-samples
样例的结构如下: 
启动seata服务让seata服务注册到Nacos上。 
1.POM文件内容
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-cloud.version>2021.0.4</spring-cloud.version>
<cloud.alibaba.version>2021.0.4.0</cloud.alibaba.version>
<nacos.version>2.1.0</nacos.version>
<cloud.version>3.1.2</cloud.version>
<druid.version>1.2.11</druid.version>
<dynamic-datasource.version>3.5.1</dynamic-datasource.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-datasource.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>${cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>${cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${cloud.version}</version>
</dependency>
</dependencies>
2.项目工程
模块的总体结构如下,这里只列出account-server的部分内容,具体内容可访问官方仓库。 
account库的数据库表
CREATE TABLE `account`
(
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
`total` decimal(10, 0) DEFAULT NULL COMMENT '总额度',
`used` decimal(10, 0) DEFAULT NULL COMMENT '已用余额',
`residue` decimal(10, 0) DEFAULT '0' COMMENT '剩余可用额度',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `account` (`id`, `user_id`, `total`, `used`, `residue`)
VALUES ('1', '1', '100', '0', '100');
每个库还得加上seata的undo_log数据表。undo-log 是 AT 模式中的核心部分 , 他是在 RM 部分完成的 , 在每一个数据库单元处理时均会生成一条 undoLog 数据。
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=17 DEFAULT CHARSET=utf8;
bootstrap.yml文件内容 具体的配置信息配置在Nacos上,所以要在bootstrap.yml上配置上Nacos的信息。
server:
port: 8081
nacos:
service:
address: 127.0.0.1:8848
spring:
application:
name: feign-account-server
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: ${nacos.service.address}
namespace: wey
config:
server-addr: ${nacos.service.address}
namespace: wey
file-extension: yml
shared-configs:
- feigin-seata-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
Nacos上的配置  Nacos上的feign-account-server-dev.yml 文件的配置内容,order模块跟storage模块的内容类似。
spring:
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
primary: master
strict: false
seata: true
seata-mode: at
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/feign-seata-account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: false
service:
vgroup-mapping:
coolpad-apioutweb-application-group: default
config:
type: nacos
nacos:
serverAddr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: seata
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
namespace: seata
feigin-seata-dev.yml 配置的是共享的配置信息,可以将公共的配置放在这个文件内。
mybatis-plus:
checkConfigLocation: false
configuration:
aggressiveLazyLoading: true
autoMappingBehavior: PARTIAL
autoMappingUnknownColumnBehavior: NONE
defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapUnderscoreToCamelCase: true
global-config:
banner: true
typeAliasesPackage: com.wey.**.entity
mapperLocations: classpath:mapper/**/*.xml
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 10000
最后集成调用成环,通过@GlobalTransaction注解开户分布式事务。
@Override
@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
public void create(Order order) {
orderDao.create(order);
stockApi.decrease(order.getProductId(),order.getCount());
accountApi.decrease(order.getUserId(),order.getMoney());
}
在最初的order会创建一个订单,然后扣减库存,然后扣减账户,账户扣减完,会回头修改订单的金额和状态,这样调用就成环了。
调用成功后seata控制台会打印提交日志。 
|