1.模式简介与选择
1.1模式简介
1.2模式选择
通过对各种模式的理解和部分模式尝试使用。我认为AT模式比较合适
理由:
①当前项目使用的是Mysql数据库,支持事务,符合AT模式的使用前提
②AT模式不需要手动编写提交或回滚代码,原代码不用做改动
③AT模式的学习资源和介绍丰富:
SpringCloudAlibaba提供的Seata使用示例是AT模式的
Seata官方快速启动也是针对AT模式,并且对AT模式的相关介绍高于其他各个模式
网上的博客较其他的模式要多
2.数据库的修改
2.1Seata数据库创建
2.1.1测试库和开发库
测试库和开发库都在 10.11.0.215的Mysql中因此,此Mysql上创建 test_seata和seata两个数据库,并且两个库分别创建3个相同的表
参考:https://github.com/seata/seata/blob/develop/script/server/db/mysql.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_gmt_modified_status` (`gmt_modified`, `status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- 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 = utf8;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
2.1.2生产库
生产库的话应该是创建一个 seata数据库即可,sql语句 同上。
2.2undo_log表的创建
在用到的数据库中创建undo_log表即可
参考:https://github.com/seata/seata/blob/develop/script/client/at/db/mysql.sql
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
`branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id',
`xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id',
`context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
`log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` DATETIME(6) NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
3.Seata-Server的部署
3.1开发环境的Seata-Server的部署
1.开发环境的Seata-Server采用的方式与开发环境nacos的使用方式相同,开发人员启动自己的Seata-Server
2.Seata-Sever配置好打包到项目中即可
3.Seata-Server中的文件配置(register.conf)
#注册在本地
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
}
#去220找配置
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "10.11.0.220:8855"
group = "SEATA_GROUP"
namespace = "dev-seata空间的id"
cluster = "default"
username = "appconnect"
password = "appconnect"
}
}
3.2测试环境的Seata-Sever部署
1.测试环境的Seata-Server采用的方式与测试环境nacos的使用方式也相同。
2.当前测试环境nacos也是重新启动一份的,所以seata-server在测试环境中也启动一份即可
3.配置文件(register.conf)
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "10.11.0.220:8855"
group = "SEATA_GROUP"
namespace = "test-seata空间的id"
cluster = "default"
username = "appconnect"
password = "appconnect"
}
}
3.3生产环境的Seata-Sever部署
1.生产环境的Seata-Server采取高可用的配置方式;
2.具体操作:在不同的生产服务器上启动多个Seata-Server即可,数量不限
3.配置文件(register.conf)
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "10.11.0.220:8855"
group = "SEATA_GROUP"
namespace = "生产服务注册空间id"
cluster = "default"
username = "appconnect"
password = "appconnect"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "10.11.0.220:8855"
group = "SEATA_GROUP"
namespace = "pro-seata空间的id"
cluster = "default"
username = "appconnect"
password = "appconnect"
}
}
4.Nacos关于Seata-Server的配置
4.1命名空间的创建
1.分别创建三个命名空间
①dev-seata:存放开发环境的seata配置
②test-seata:存放测试环境的seata配置
③pro-seata:存放生产环境的seata配置
4.2各个配置空间的配置初始化
参考:https://github.com/seata/seata/tree/develop/script/config-center
先准备好以下2个文件config.txt和nacos-config.sh
1.准备config.txt
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
service.vgroupMapping.my_test_tx_group=default
service.enableDegrade=false
service.disableGlobalTransaction=false
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=false
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=username
store.db.password=password
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
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
2.准备nacos-config.sh
#!/usr/bin/env bash
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at、
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
while getopts ":h:p:g:t:u:w:" opt
do
case $opt in
h)
host=$OPTARG
;;
p)
port=$OPTARG
;;
g)
group=$OPTARG
;;
t)
tenant=$OPTARG
;;
u)
username=$OPTARG
;;
w)
password=$OPTARG
;;
?)
echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
exit 1
;;
esac
done
if [[ -z ${host} ]]; then
host=localhost
fi
if [[ -z ${port} ]]; then
port=8848
fi
if [[ -z ${group} ]]; then
group="SEATA_GROUP"
fi
if [[ -z ${tenant} ]]; then
tenant=""
fi
if [[ -z ${username} ]]; then
username=""
fi
if [[ -z ${password} ]]; then
password=""
fi
nacosAddr=$host:$port
contentType="content-type:application/json;charset=UTF-8"
echo "set nacosAddr=$nacosAddr"
echo "set group=$group"
failCount=0
tempLog=$(mktemp -u)
function addConfig() {
curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$1&group=$group&content=$2&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
if [[ -z $(cat "${tempLog}") ]]; then
echo " Please check the cluster status. "
exit 1
fi
if [[ $(cat "${tempLog}") =~ "true" ]]; then
echo "Set $1=$2 successfully "
else
echo "Set $1=$2 failure "
(( failCount++ ))
fi
}
count=0
for line in $(cat "./config.txt" | sed s/[[:space:]]//g); do
(( count++ ))
key=${line%%=*}
value=${line#*=}
addConfig "${key}" "${value}"
done
echo "========================================================================="
echo " Complete initialization parameters, total-count:$count , failure-count:$failCount "
echo "========================================================================="
if [[ ${failCount} -eq 0 ]]; then
echo " Init nacos config finished, please start seata-server. "
else
echo " init nacos config fail. "
fi
4.2.1开发环境pro-seata命名空间的seata配置信息初始化
1.将config.txt中数据库配置修改
service.vgroupMapping.yurun_dev_tx_group=default
store.db.url=jdbc:mysql://10.11.0.215:3306/seata?useUnicode=true
2.执行命令
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
实例:
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t f2edbd24-10e8-4143-b01b-3b6a2c916d38 -u nacos -w nacos
4.2.2测试环境test-seata命名空间的seata配置信息初始化
1.将config.txt中的数据库配置修改
service.vgroupMapping.yurun_test_tx_group=default
store.db.url=jdbc:mysql://10.11.0.215:3306/test_seata?useUnicode=true
2.执行命令
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
实例:
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 49e16ac0-1ff4-49e2-997e-6a3c236a536b -u nacos -w nacos
4.2.3生产环境pro-seata命名空间的seata配置信息初始化
1.将config.txt中的数据库配置修改
service.vgroupMapping.yurun_pro_tx_group=default
store.db.url=jdbc:mysql://生产库ip:3306/seata?useUnicode=true
2.执行命令
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
实例:
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 4eacde77-104b-4ae5-82a7-8131f1a07740 -u nacos -w nacos
5.各个微服务的seata相关的配置
5.1pom文件
分布式事务的参与者需要引入seata
<!--seata-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
</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>
5.2开发环境关于seata的nacos配置文件(seata-client.yaml)
seata:
tx-service-group: yurun_dev_tx_group
registry:
type: nacos
nacos:
server-addr: localhost:8848
username: nacos
password: nacos
config:
type: nacos
nacos:
username: appconnect
password: appconnect
namespace: dev-seata命名空间id
serverAddr: 10.11.0.220:8855
5.3测试环境关于seata的nacos配置文件(seata-client.yaml)
seata:
tx-service-group: yurun_test_tx_group
registry:
type: nacos
nacos:
server-addr: localhost:8848
username: nacos
password: nacos
config:
type: nacos
nacos:
username: appconnect
password: appconnect
namespace: test-seata命名空间id
serverAddr: 10.11.0.220:8855
5.4生产环境关于seata的nacos配置文件(seata-client.yaml)
seata:
tx-service-group: yurun_pro_tx_group
registry:
type: nacos
nacos:
server-addr: 10.11.0.220:8855
username: appconnect
password: appconnect
namespace: 生产的服务注册命名空间id
config:
type: nacos
nacos:
username: appconnect
password: appconnect
namespace: pro-seata命名空间id
serverAddr: 10.11.0.220:8855
5.5总结
对于seata-client.yaml分别在10.11.0.220的nacos中不同命名空间放置即可,在每个需要分布式事务的bootstrap.yml中的nacos配置文件中添加即可:
6.使用
在需要分布式事务的方法上添加@GlobalTransactional
但是对于我们电商现在的中台,只有controller层,异常不给抛出,Controller方法加注解也没用,所以对代码改造是:
在中台添加一个Service层,在service层方法上添加注解即可实现分布式事务