Mastering Seata: A Complete Guide to Distributed Transaction Setup and Configuration
This article provides a comprehensive overview of Seata, covering its origins, supported transaction modes, installation steps, database initialization, detailed configuration for registry and Apollo, client setup, transaction lifecycle components, and scheduled tasks that manage global and branch transaction states.
Introduction
Seata is an open‑source distributed transaction framework that provides four transaction modes: AT (automatic compensation), TCC (two‑phase commit), SAGA (long‑running transactions) and XA (standard XA interface). It integrates with common RPC frameworks such as Dubbo, Spring Cloud, Sofa‑RPC, Motan and gRPC.
AT – automatic compensation, supports MySQL, Oracle, PostgreSQL, TiDB (H2 in development).
TCC – can be mixed with AT for higher flexibility.
SAGA – solves long‑running transaction scenarios.
XA – works with databases that implement the XA interface.
High availability – cluster mode based on database storage.
Server Installation
Download
Example uses Seata 1.4.2 with Zookeeper as the registry and Apollo as the configuration center. Download link: https://seata.io/zh-cn/blog/download.html
Database Initialization
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime(6) DEFAULT NULL,
`gmt_modified` datetime(6) DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int(11) DEFAULT NULL,
`begin_time` bigint(20) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_gmt_modified_status` (`gmt_modified`,`status`) USING BTREE,
KEY `idx_transaction_id` (`transaction_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `lock_table` (
`row_key` varchar(128) NOT NULL,
`xid` varchar(96) DEFAULT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`branch_id` bigint(20) NOT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`table_name` varchar(32) DEFAULT NULL,
`pk` varchar(36) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;Configuration
registry.conf
registry {
type = "zk"
zk {
cluster = "default"
serverAddr = "xxx:1500"
sessionTimeout = 60000
connectTimeout = 20000
}
}
config {
type = "apollo"
apollo {
appId = "arch-seata-server"
apolloMeta = "http://xxx:8080"
apolloConfigService = "http://xxx:8080"
namespace = "application"
apolloAccesskeySecret = ""
cluster = "test"
seata = "test"
}
}Apollo configuration (transport, store, metrics, etc.)
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
store.mode = db
store.db.datasource = druid
store.db.dbType = mysql
store.db.driverClassName = com.mysql.jdbc.Driver
store.db.url = jdbc:mysql://xxx:3306/server_seata?rewriteBatchedStatements=true
store.db.user =
store.db.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
server.distributedLockExpireTime = 10000
server.undo.logSaveDays = 7
server.undo.logDeletePeriod = 86400000
log.exceptionRate = 100
transport.serialization = seata
transport.compressor = none
metrics.enabled = false
metrics.registryType = compact
metrics.exporterList = prometheus
metrics.exporterPrometheusPort = 9898Start Server
Add -Denv=FAT to the startup script (e.g., bat.sh).
Client Setup
Maven Dependency
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>AT Mode Table
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'increment id',
`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 NOT NULL COMMENT 'create datetime',
`log_modified` datetime NOT NULL COMMENT 'modify datetime',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;Client Configuration
# Service group mapping
seata.tx-service-group = my_test_tx_group
service.vgroupMapping.my_test_tx_group = default
# Registry (Zookeeper)
seata.registry.type = zk
seata.registry.zk.server-addr = xxx:2181
seata.registry.zk.session-timeout = 60000
seata.registry.zk.connect-timeout = 20000
# Apollo configuration
seata.config.type = apollo
seata.config.apollo.apollo-meta = http://xxx:8080
seata.config.apollo.app-id = arch-seata-debug
seata.config.apollo.namespace = application
# Transport and client settings (same as server example)
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
# Additional client options
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.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
client.loadBalance.type = RandomLoadBalance
client.loadBalance.virtualNodes = 10
log.exceptionRate = 100
transport.serialization = seata
transport.compressor = noneAT Mode Example
@GlobalTransactional(name = "testAT")
public void testAT() {
// local transaction
dosql();
// RPC call
dorpc();
}TCC Mode Example
@GlobalTransactional(name = "testTCC")
public void testTCC() {
TccActionTwoImpl.prepare(null, "a", new ArrayList());
TccActionOneImpl.prepare(null);
}
@LocalTCC
public interface TccActionTwo {
@TwoPhaseBusinessAction(name = "DubboTccActionTwo", commitMethod = "commit", rollbackMethod = "rollback")
boolean prepare(BusinessActionContext actionContext,
@BusinessActionContextParameter(paramName = "b") String b,
@BusinessActionContextParameter(paramName = "c", index = 1) List list);
boolean commit(BusinessActionContext ctx);
boolean rollback(BusinessActionContext ctx);
}
@LocalTCC
public interface TccActionOne {
@TwoPhaseBusinessAction(name = "DubboTccActionOne", commitMethod = "commit", rollbackMethod = "rollback")
boolean prepare(BusinessActionContext actionContext);
boolean commit(BusinessActionContext ctx);
boolean rollback(BusinessActionContext ctx);
}Seata‑Server Architecture
TC (Transaction Coordinator) – maintains global and branch transaction states and drives commit/rollback.
TM (Transaction Manager) – defines the scope of a global transaction (begin, commit, rollback).
RM (Resource Manager) – manages branch resources, registers branch transactions with TC, and reports branch status.
Global Transaction Status Codes
Begin (1), Committing (2), CommitRetry (3), Rollbacking (4), RollbackRetrying (5), TimeoutRollbacking (6), TimeoutRollbackRetrying (7), AsyncCommitting (8), Committed (9), CommitFailed (10), Rollbacked (11), RollbackFailed (12), TimeoutRollbacked (13), TimeoutRollbackFailed (14), Finished (15), Unknown (0).
Branch Transaction Status Codes
Registered (1), PhaseOne_Done (2), PhaseOne_Failed (3), PhaseOne_Timeout (4), PhaseTwo_Committed (5), PhaseTwo_CommitFailed_Retryable (6), PhaseTwo_CommitFailed_Unretryable (7), PhaseTwo_Rollbacked (8), PhaseTwo_RollbackFailed_Retryable (9), PhaseTwo_RollbackFailed_Unretryable (10), Unknown (0).
Scheduled Tasks
Retry rollback for timed‑out global transactions (interval server.recovery.rollbackingRetryPeriod=1000ms).
Retry commit for timed‑out global transactions (interval server.recovery.committingRetryPeriod=1000ms).
Async commit handling (interval server.recovery.asynCommittingRetryPeriod=1000ms).
Transaction timeout detection – moves a transaction to TimeoutRollbacking and enqueues it for retry.
Undo‑log cleanup (interval server.undo.logDeletePeriod=86400000ms, retain logs for 7 days).
Registration of RM and TM
Application Startup
When a Spring Boot application starts, SeataAutoConfiguration loads GlobalTransactionScanner, which calls TMClient.init and RMClient.init using the configured applicationId and txServiceGroup. Each application therefore acts as both TM and RM.
TM Registration
TM sends applicationId and transactionServiceGroup to TC. TC stores the session for heartbeat maintenance.
RM Registration
RM sends resourceIds, applicationId and transactionServiceGroup to TC. In AT mode, resourceIds correspond to database instances; in TCC mode they correspond to the @TwoPhaseBusinessAction name values.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
