環境配置
-
虛擬機中安裝centos8,centos8中安裝docker,docker中安裝mysql8.0.27、nacos2.0.3、seata1.3.0
-
啟動mysql容器,win10系統上navicat能連接到mysql容器,並導入如下數據庫
-
-
可在win10系統上下創建2個文件,之后上傳到centos8服務器的/home/mydocker/seata/config目錄
-
nacos控制台中新建命名空間dev
## file.conf;使seata-server連接mysql中的數據庫seata
store {
## store mode: file、db
mode = "db"
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://192.168.96.172:3306/seata"
user = "root"
password = "123456"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
}
}
## testregistry.conf;使nacos作為seata-server的服務注冊中心和服務配置中心
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "192.168.96.172:8848"
group = "SEATA_GROUP"
namespace = "3ac15cbc-5ad3-4441-b5d5-a6fb1aa8a7f7"
cluster = "default"
username = ""
password = ""
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "192.168.96.172:8848"
namespace = "3ac15cbc-5ad3-4441-b5d5-a6fb1aa8a7f7"
group = "SEATA_GROUP"
username = ""
password = ""
}
}
- 上傳到centos8服務器
pscp -P 22 C:\file.conf root@192.168.96.172:/home/mydocker/seata/config
pscp -P 22 C:\testregistry.conf root@192.168.96.172:/home/mydocker/seata/config
- 啟動nacos,同時啟動seata
docker run --name seata-server -p 8091:8091 -e SEATA_CONFIG_NAME=file:/root/seata-config/testregistry -e SEATA_IP=192.168.96.172 -v /home/mydocker/seata/config:/root/seata-config -d seataio/seata-server:1.3.0
-
win10系統上打開瀏覽器,輸入 http://192.168.96.172:8848/nacos/ 打開nacos控制台,可在服務列表查看注冊進來的seata服務
-
mkdir -p /home/mydocker/seata # 新建文件夾
-
touch config.txt # 新建文件,復制官方配置到該文件
-
config.txt中配置分組、數據源
service.vgroupMapping.my_test_tx_group=default
service.vgroupMapping.account-service-seata=default
service.vgroupMapping.storage-service-seata=default
service.default.grouplist=192.168.96.172:8091
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.96.172:3306/seata?useUnicode=true
store.db.user=root
store.db.password=123456
-
mkdir -p /home/mydocker/seata/nacos # 新建文件夾
-
touch nacos-config.sh # 新建文件,復制官方配置到該文件
官方配置地址 -
進入nacos-config.sh所在路徑,執行如下命令
sh nacos-config.sh -h 192.168.43.150 -p 8848 -g SEATA_GROUP -t 命名空間id -u nacos -w nacos
- 導入成功后可在nacos控制台配置列表查看
- config.txt導入nacos配置管理后,就可以不將file.conf和registry.conf放到我們的項目中
項目配置
- 父工程依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
- 3個子模塊中添加依賴,pom中導入對應的seata依賴版本
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.3.0</version>
</dependency>
- 3個子模塊中配置yml
spring:
cloud:
alibaba:
seata:
enabled: true
application-id: seata-server # nacos中seata服務端的注冊名稱
enable-auto-data-source-proxy: true # 開啟數據庫自動代理
tx-service-group: my_test_tx_group # 這里填寫上傳config.txt時對應此工程的vgroupMapping配置
- 3個子模塊中啟動類配置
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
- 3個子模塊中添加registry.conf文件
registry {
type = "nacos"
nacos {
serverAddr = "192.168.96.172:8848"
namespace = "3ac15cbc-5ad3-4441-b5d5-a6fb1aa8a7f7"
cluster = "default"
group = "SEATA_GROUP"
}
}
config {
type = "nacos"
nacos {
serverAddr = "192.168.96.172:8848"
namespace = "3ac15cbc-5ad3-4441-b5d5-a6fb1aa8a7f7"
cluster = "default"
group = "SEATA_GROUP"
}
}
- 3個子模塊中編寫DataSourceConfig配置類
# yml文件中指定數據源
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.96.172:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
# 編寫配置類
@Configuration
public class DataSourceConfig {
// 1. 綁定yml中的數據源
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
return new DruidDataSource();
}
// 2. 構建datasource代理對象,替換原來的數據源
@Bean
public DataSourceProxy dataSourceProxy(DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
// 3. mybatis相關配置
@Bean
public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean.getObject();
}
}
-
方法上添加注解 @GlobalTransactional(rollbackFor = Exception.class)
-
模擬1個超時異常,瀏覽器發送請求進行測試;測試結果,數據庫數據數據無誤
-
注釋掉注解@GlobalTransactional,再次發送請求進行測試
-
測試結果:余額減100
-
-
庫存減10
-
-
生成了1張訂單,但訂單狀態為0表示用戶未支付,可用戶的余額表顯示減了100;說明出現錯誤后數據沒有回滾
-
————————————————————————— 分割線 ———————————————————————————
-
引入依賴;首先排除spring-cloud-starter-alibaba-seata中的seata-all
-
-
每個微服務對應的數據庫加入undo_log表
-
編寫配置代理數據類DataSourceConfig
-
啟動類上排除DataSourceAutoConfiguration類
-
每個微服務resources路徑下添加registry.conf文件;注意命名空間和分組
-
-
補充:使用cloud alibaba2.1.4則可不添加registry.conf,將該文件中配置添加到yml文件中
-
-
每個微服務的yml中指定分組
-
-
添加注解@GlobalTransactional
常見錯誤
- error1:no available server to connect
# 解決方案
# yml配置中添加屬性spring.cloud.alibaba.seata.tx-service-group,值需與file.conf中的分組一致
spring:
cloud:
alibaba:
seata:
#自定義事務組名稱需要與seata-server中的對應
tx-service-group: my_test_tx_group
-
win10系統中安裝seata0.9,file.conf中service模塊設置分組service.vgroupMapping;docker中安裝seata1.3.0發現無service模塊,不在file.conf中配置分組,而在config.txt中配置
-
pom中到seata依賴版本與安裝的seata版本需要一致
-
若使用seata1.4.0,則對應使用cloud alibaba2.1.1
-
-
若使用seata1.3.0,則對應使用cloud alibaba2.1.2及其以上版本
-
-
resources路徑下的conf后綴結尾的文件圖標必須如下,否則表示沒有被識別
-
-