SprinrBoot整合Seata使用AT模式解決多數(shù)據(jù)源分布式事務(wù)
分布式事務(wù)場景:
1.應(yīng)用中使用多數(shù)據(jù)源颜说,跨多個數(shù)據(jù)庫
2.跨多個應(yīng)用進程
Seata是阿里巴巴開源的分布式事務(wù)中間件,以高效并且對業(yè)務(wù)0 侵入的方式汰聋,解決微服務(wù)場景下面臨的分布式事務(wù)問題脑沿。
Seata下載地址:https://github.com/seata/seata/releases
進入官網(wǎng)不會下載,請參考如下截圖:
1.下載Window版本后马僻,打開如圖所示
2.其中Context.txt配置如圖
service.vgroupMapping.default_tx_group=default
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1/:3306/nacos-mysql?useUnicode=true
store.db.user=root
store.db.password=123456
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
3.然后進入seata-server1.4.2\conf目錄中修改對應(yīng)的參數(shù)
4.開始編輯file.conf文件
5.配置seata-server-1.4.2/conf/registry.conf
6.下載Seata對應(yīng)的Mysql腳本:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql
下面還有Oracle數(shù)據(jù)庫的腳本,也可以前往Github獲得所有SQl腳本
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`status` TINYINT NOT NULL,
`application_id` VARCHAR(32),
`transaction_service_group` VARCHAR(32),
`transaction_name` VARCHAR(128),
`timeout` INT,
`begin_time` BIGINT,
`application_data` VARCHAR(2000),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR(256),
`branch_type` VARCHAR(8),
`status` TINYINT,
`client_id` VARCHAR(64),
`application_data` VARCHAR(2000),
`gmt_create` DATETIME(6),
`gmt_modified` DATETIME(6),
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(128),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`),
KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `distributed_lock`
(
`lock_key` CHAR(20) NOT NULL,
`lock_value` VARCHAR(20) NOT NULL,
`expire` BIGINT,
primary key (`lock_key`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
7.如果是Oracle對應(yīng)的腳本如下:
創(chuàng)建名稱為seata的數(shù)據(jù)庫注服,字符集utf8mb4韭邓、排序規(guī)則utf8mb4_general_ci
nacos的配置首先要修改連接的數(shù)據(jù)庫,在oracle新建一個SEATA命名空間和用戶溶弟,并插入三張表(global_table,branch_table,lock_table)女淑,腳本如下
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE global_table
(
xid VARCHAR2(128) NOT NULL,
transaction_id NUMBER(19),
status NUMBER(3) NOT NULL,
application_id VARCHAR2(32),
transaction_service_group VARCHAR2(32),
transaction_name VARCHAR2(128),
timeout NUMBER(10),
begin_time NUMBER(19),
application_data VARCHAR2(2000),
gmt_create TIMESTAMP(0),
gmt_modified TIMESTAMP(0),
PRIMARY KEY (xid)
);
CREATE INDEX idx_gmt_modified_status ON global_table (gmt_modified, status);
CREATE INDEX idx_transaction_id ON global_table (transaction_id);
-- the table to store BranchSession data
CREATE TABLE branch_table
(
branch_id NUMBER(19) NOT NULL,
xid VARCHAR2(128) NOT NULL,
transaction_id NUMBER(19),
resource_group_id VARCHAR2(32),
resource_id VARCHAR2(256),
branch_type VARCHAR2(8),
status NUMBER(3),
client_id VARCHAR2(64),
application_data VARCHAR2(2000),
gmt_create TIMESTAMP(6),
gmt_modified TIMESTAMP(6),
PRIMARY KEY (branch_id)
);
CREATE INDEX idx_xid ON branch_table (xid);
-- the table to store lock data
CREATE TABLE lock_table
(
row_key VARCHAR2(128) NOT NULL,
xid VARCHAR2(96),
transaction_id NUMBER(19),
branch_id NUMBER(19) NOT NULL,
resource_id VARCHAR2(256),
table_name VARCHAR2(32),
pk VARCHAR2(36),
gmt_create TIMESTAMP(0),
gmt_modified TIMESTAMP(0),
PRIMARY KEY (row_key)
);
CREATE INDEX idx_branch_id ON lock_table (branch_id);
修改seata配置
store.db.dbType=oracle
# 這里是個坑OracleDriver并不存在在seata服務(wù)代碼里
store.db.driverClassName=oracle.jdbc.OracleDriver
store.db.url=jdbc:oracle:thin:@192.168.1.135:1521:helowin
store.db.user=SEATA
store.db.password=SEATA
8.業(yè)務(wù)數(shù)據(jù)庫中添加項目數(shù)據(jù)庫undo_log(就是你應(yīng)用平臺的數(shù)據(jù)庫)
和mysql一樣,項目數(shù)據(jù)庫也需要每個庫都加入undo_log表,腳本如下
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE undo_log
(
id NUMBER(19) NOT NULL,
branch_id NUMBER(19) NOT NULL,
xid VARCHAR2(100) NOT NULL,
context VARCHAR2(128) NOT NULL,
rollback_info BLOB NOT NULL,
log_status NUMBER(10) NOT NULL,
log_created TIMESTAMP(0) NOT NULL,
log_modified TIMESTAMP(0) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT ux_undo_log UNIQUE (xid, branch_id)
);
COMMENT ON TABLE undo_log IS 'AT transaction mode undo table';
-- Generate ID using sequence and trigger
CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1;
9.創(chuàng)建nacos-config.sh
內(nèi)容從Github鏈接nacos-config.sh中復(fù)制粘貼即可
10.然后再來看一下Seata的官方文檔
打開找到Nacos配置中心(Nacos是目前最主流的注冊中心)
執(zhí)行命令自動構(gòu)建Nacos配置
11.啟動Nacos創(chuàng)建一個命令空間如圖
12.初始化腳本數(shù)據(jù)到nacos
在執(zhí)行以下命令辜御,將配置自動加載到Nacos中
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 此為上面的Nacos的Namespace的ID -u nacos -w nacos
然后查看Nacos中是否有配置
13.下載的Nacos中腳本下載說明
14.直接訪問在Github中獲取Seata中所需的文件
點擊 參考部署指南
到Github獲取sql腳本/各個配置中心參數(shù)導入腳本鸭你,config.txt/server端數(shù)據(jù)庫腳本
15.SpringBoot中添加配置
也可以參考官方文檔http://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
點擊查看官方文檔
<!--seata 分布式事務(wù)(使用這種方式可以自動傳遞xid)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.2.0.RELEASE</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>1.4.0</version>
<exclusions>
<exclusion>
<artifactId>druid</artifactId>
<groupId>com.alibaba</groupId>
</exclusion>
</exclusions>
</dependency>
yaml應(yīng)用服務(wù)配置
seata: ## Seata分布式事務(wù)配置管理
enabled: true
enable-auto-data-source-proxy: true
# seata 事務(wù)組編號 用于TC集群名 # 必須和config.txt里面配置的屬性一致
tx-service-group: default_tx_group
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
config:
# 必須寫nacos,否則默認file
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
username: nacos
password: nacos
namespace: nacos的namespaced例如:65f556f2-1dc4-4b13-af44-6914f7f5bf73
service:
# 事務(wù)組對應(yīng)的集群名稱
vgroup-mapping:
default_tx_group: default
disable-global-transaction: false
client:
rm:
report-success-enable: false
15.如果以上都配置完畢擒权,就啟動Seata/應(yīng)用服務(wù)
BUG問題
can not get cluster name in registry config
'service.vgroupMapping.account-service-fescar-service-group'
please make sure registry config correct