环境
Nacos
Nacos Version
:2.0.3
Seata
Seata Version
: 1.4.2
Demo Application:
System
: macOS 10.14.6
JDK
: 1.8.0_251
Spring Boot
:2.2.13.RELEASE
Spring Cloud
:Hoxton.SR12
Spring Cloud Alibaba
: 2.2.5.RELEASE
Seata Server
建表
Seata server 关键表 global_table
、branch_table
、lock_table
建表脚本mysql.sql
下载
地址:seata server
选择1.4.2
版本下载,解压。
Seata Server 配置
conf目录下registry.conf
:
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "xxx.xxx.xxx.xxx:8848"
group = "SEATA_GROUP"
namespace = "public"
cluster = "default"
username = ""
password = ""
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "xxx.xxx.xxx.xxx:8848"
namespace = "public"
group = "SEATA_GROUP"
username = ""
password = ""
dataId = "seataServer.properties"
}
}
Nacos 配置
在Nacos namespace=public,group=SEATA_GROUP下创建文件seataServer.properties
。内容可以复制config.txt
修改以下属性:
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://xxx.xxx.xxx.xxx:3306/d_seata?useUnicode=true
store.db.user=xxx
store.db.password=xxx
启动
bin目录下执行./seata-server.sh
验证
启动无报错,且在nacos上可以看到注册的服务列表即可。
Seata Client
四个服务order-service
、storage-service
、account-service
、business-service
。关系如下:
官网demo:seata-samples
pom配置
<!-- nacos config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- nacos discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>${alibaba.cloud.version}</version>
<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>${seata.version}</version>
</dependency>
属性配置
以storage-service
服务配置为例:
server:
port: 10019
spring:
application:
name: storage-service
cloud:
nacos:
discovery:
server-addr: xxx.xxx.xxx.xxx:8848
config:
server-addr: xxx.xxx.xxx.xxx:8848
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/d_seata?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =GMT%2B8
username: xxx
password: xxx
#hikari数据库连接池
hikari:
pool-name: HikariCP
minimum-idle: 10 #最小空闲连接数量
idle-timeout: 600000 #空闲连接存活最大时间,默认600000(10分钟)
maximum-pool-size: 100 #连接池最大连接数,默认是10
auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true
max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000
connection-test-query: SELECT 1
#设置feign 客户端超时时间(openFeign默认支持ribbon)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 25000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 25000
seata:
enabled: true
application-id: ${spring.application.name} # 同spring.application.name 配置的项目名称
tx-service-group: my_test_tx_group # 分组key部分 配置中心有对应分组值ervice.vgroupMapping.my_test_tx_group=default
enable-auto-data-source-proxy: true #开启数据库代理
config:
type: nacos
nacos:
server-addr: xxx.xxx.xxx.xxx:8848
group : SEATA_GROUP
namespace: public
dataId: seataServer.properties
registry:
type: nacos
nacos:
application: seata-server
server-addr: xxx.xxx.xxx.xxx:8848
group : SEATA_GROUP
namespace: public
cluster: default
注解
在开启全局事务的方法上添加@GlobalTransactional
,如business-service
:
@GlobalTransactional(rollbackFor = Exception.class)
public void purchase(String userId, String commodityCode, int orderCount) {
// 获取全局事务id
log.info("XID==>{}", RootContext.getXID());
// 减库存
storageFeignClient.deduct(commodityCode, orderCount);
// 下单
orderFeignClient.create(userId, commodityCode, orderCount);
}
在本地事务方法上添加@Transactional
,如storage-service
:
@Transactional(rollbackFor = Exception.class)
public void deduct(String commodityCode, int count) {
Storage storage = storageDAO.findByCommodityCode(commodityCode);
storage.setCount(storage.getCount() - count);
storageDAO.save(storage);
}
注意: 若一个方法开启全局事务的同时,也开启本地事务。则两个注解都要添加。
启动服务
启动四个clinet服务,应在nacos看到对应服务的注册列表。
验证
business-service
购买下单,模拟全局事务提交:
curl http://localhost:10017/purchase/commit
返回true,查看库存表。
库存表货物2001(初始数量1000)已扣减数量1。查看账户表。
用户1001已成功扣减金额5。
购买下单,模拟全局事务回滚
curl http://localhost:10017/purchase/rollback
返回false。
查看库存表。
库存表货物2001没有扣减数量。查看账户表。
账户表中用户1002的金额没有扣减。
链接: