Introduction to the
Seata is an open source distributed transaction solution dedicated to providing high performance and easy to use distributed transaction services. Seata will provide users with AT, TCC, SAGA and XA transaction modes to create a one-stop distributed solution for users. AT mode is used in our project. AT mode is divided into two phases: Phase 1: business data and rollback log records are committed in the same local transaction, and local locks and connection resources are released. Phase two: Commit asynchronously, done very quickly. Rollback is compensated in reverse by the rollback log of one phase.
1. Introduce dependencies into the project to enable SEATA transactions
The jar package introduced in pom. XML before 1.4.2 does not support a data ID to store all seATA server configuration information. After 1.4.2, it supports a configuration file.
<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> <! - the use of1.42.Version, A configuration file containing all other configuration information --> <dependency> <groupId> IO. Seata </groupId> <artifactId>seata-spring-boot-starter</artifactId> <version>${seata.version}</version> </dependency>Copy the code
About the spring Cloud Alibaba ecology version reference address: github.com/alibaba/spr…
2. Set up the SeATA Server
Server download address: github.com/seata/seata… To decompress and configure the downloaded project. Download the configured template file from github.com/seata/seata…
(1) seata/conf/file. Conf
This configuration item is the storage configuration of the SEATA server. The storage mode is DB, and then the connection information of the database and the global table for transaction processing (the default table name is ok) are configured.
Store {## store mode: file, db, redis mode ="db"
## rsa decryption public key
publicKey = ""
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## datasource = "dbcp"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
## mysql 5.xx
## driverClassName = "com.mysql.jdbc.Driver"
## mysql 8.0
driverClassName = "com.mysql.cj.jdbc.Driver"# #if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
url = "jdbc:mysql://ip:port/umapp_appcenter? rewriteBatchedStatements=true"
## url = "jdbc:mysql://ip:port/umapp_appcenter? useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai"
user = "appcenter"
password = "123456"
minConn = 5
maxConn = 100
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000}}Copy the code
Note: The driverClassName driver configuration depends on the mysql version: Mysql5.+ driverClassName = “com.mysql.jdbc.driver” mysql8 driverClassName = “com.mysql.cj.jdbc.driver”
(2) seata/conf/registry. Conf
You need to configure the selected registry type (NACOS) and the connection information of the registry. Configure the type and connection information of the center.
Registry {# file, NACOS, Eureka, Redis, ZK, Consul, ETCD3, SOFA type ="nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:7500"
group = "SEATA_GROUP"
namespace = "public"
cluster = "default"
username = "nacos"
password = "nacos"}} config {# file, nacos, Apollo, zk, consul, etcd3 type ="nacos"
nacos {
serverAddr = "127.0.0.1:7500"
namespace = "public"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
dataId = "seataServer.properties"}}Copy the code
Note:
(1) when nacos open security configuration (in nacos conf/application. The properties in the configuration nacos. Core. The auth. Enabled = true), the connection information for nacos will bring the information such as user name, password
(2) dataId = “seataserver. properties” can be used to read configuration information only after seata1.4.2
(3) script/config-center/config.txt:
This configuration information is related to the seATA transaction. When the data ID is created in NACOS, the content of the text value is pasted into the seataserver.properties configuration item. Seata uses version 1.4.2, and the new data ID file type is selected as Properties. With seata versions prior to 1.4.2, each of the following configuration items is an entry in NACOS, Nacos-config. sh under script/config-center/nacos/ or nacos-config.py (python script) You can refer to blog.csdn.net/ZHANGLIZENG…
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=true
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
transport.serialization=seata
transport.compressor=none
# server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
# store
# model to the db
store.mode=db
store.lock.mode=file
store.session.mode=file
# store.publicKey=""
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
Change to the seata service database created abovestore.db.url=jdbc:mysql://ip:port/umapp_appcenter? useUnicode=true&rewriteBatchedStatements=true
Change your database username to your own
store.db.user=appcenter
Change your database passwordstore.db.password=123456 store.db.minConn=5 store.db.maxConn=30 store.db.globalTable=global_table store.db.branchTable=branch_table store.db.distributedLockTable=distributed_lock store.db.queryLimit=100 Store. Db. LockTable = lock_table store. Db. MaxWait = 5000 store. Redis. Mode = single store. Redis. Single. Host = 127.0.0.1 store.redis.single.port=6379# store.redis.sentinel.masterName=""
# store.redis.sentinel.sentinelHosts=""
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
# store.redis.password=""
store.redis.queryLimit=100
# log
log.exceptionRate=100
# metrics
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
# service
# Name a vgroupMapping yourself
service.vgroupMapping.my_test_tx_group=default
service.default.grouplist=ip:port
service.enableDegrade=false
service.disableGlobalTransaction=false
# client
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.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
Copy the code
Pay attention to the point
(1). Service. VgroupMapping. My_test_tx_group. = the default my_test_tx_group required with the bootstrap yml configured in seata. Tx – service – the value of the group.
(2). Service. VgroupMapping. My_test_tx_group = default configuration default must be equal to the registry. The conf configured in cluster = “default”.
③. Store. mode= If db is set to db mode, you need to configure connection information for DB database mode store.db.url, store.db.user, and store.db.password. The global_table, BRANch_table, and LOCK_table tables stored in this database record global transaction information
(4). The store. The db. The driverClassName configuration mysql5. + use driverClassName = “. Com. Mysql. JDBC Driver “mysql8 use driverClassName = “com.mysql.cj.jdbc.Driver”
(5). The service. Default. Grouplist = IP: port to access seata server address and port (registry for the file using only), 8091 is the default port, can also modify the start port, when start the project with port: seata-server.bat -p 18091 sh seata-server.sh -p 18091
⑥ To configure the seata server cluster, you only need to specify different ports and node numbers when starting the Seata Server service. Configure the contents of file.conf and registry to be consistent.
Windows startup:
seata-server.bat -p 18091 -n 1
seata-server.bat -p 8091 -n 2
In Linux, run sh seata-server.sh -p 18091-n 1
sh seata-server.sh -p 8091 -n 2
⑦ When the client starts, you can see whether it successfully registers with the Seata server
3. Create the required transaction table
Global_table: global transaction table branch_table: branch information table LOCK_table: locked table The preceding three tables must be created on the DB configured in file.conf of the SEATA server.
Global transaction table
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;
Branch table -
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 lock table
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),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`))ENGINE = INNODB
DEFAULT CHARSET = utf8;
-- New version of Seata add lock table
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);
Copy the code
Undo_log: Rollback log table This table is required for each database where seATA transaction operations need to be enabled.
-- Log file table --
CREATE TABLE IF NOT EXISTS `undo_log`
(
`branch_id` BIGINT NOT NULL COMMENT 'branch transaction id'.`xid` VARCHAR(128) 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';
Copy the code
Note:
After seata1.4.2, the date type of the table to be rolled back cannot be datetime, but timestamp can be used
4. Configure the client
The client that needs to enable SEATA transactions needs to configure the SEATA registry and configuration center and use relevant annotations to enable transactions.
(1) the bootstrap. Yml
Add configuration information to the project with values consistent with those in registry. Conf of the SeATA server.
seata:
enabled: true
enable-auto-data-source-proxy: trueWhether to enable automatic proxy for data sourcestrueTx-service-group: my_test_tx_group: my_test_tx_group Nacos: application: seata-server: seata-server Nacos # configure namespace for your own seATA service:defaultConfigure your own seATA service clusterdefaultConfig: type: nacos # default file seata.service nacos Server -addr: # configure the nacOS address group: SEATA_GROUP # configure the nacos username: Nacos # configure your own password namespace: Seataserver.properties # configure dataId for seataserver.properties # configure dataId for seataserver.properties # configure dataId for seataserver.properties # configure dataId for seataserver.propertiesCopy the code
(2) Spring Boot startup program to add automatic data proxy
Using annotations: @ EnableAutoDataSourceProxy
Example:
@EnableAutoDataSourceProxy
@EnableDiscoveryClient
@SpringBootApplication
public class UmappCloudServiceAppcenterApplication {
public static void main(String[] args) { SpringApplication.run(UmappCloudServiceAppcenterApplication.class, args); }}Copy the code
(3) Use annotations to open transactions
@apiOperation (" Add test data ")
@PostMapping("/addUmappTestSeata")
@GlobalTransactional
@GlobalLock
public Result<UmappTest> addUmappTestSeata(String name,Integer age,String sex) {
Result<UmappTest> result = umappTestService.addUmappTest(name,age,sex);
Result temp = seataTestFeign.addSeataTest();// Add seATA test data
//int i = 1/0;
return result;
Copy the code