Quick Guide: Setting Up Nacos & Seata for Distributed Transactions
This tutorial walks through the rapid installation of Nacos in MySQL mode, the configuration of Seata 1.5.0, the creation of required database tables, the development of three micro‑services (stock, order, account) with Spring Cloud Alibaba, and the verification of global transaction rollback using a sample purchase scenario.
Environment Setup
Nacos Setup
Download the latest Nacos version and start it directly. The default console credentials are nacos/nacos. MySQL credentials are root/root and nacos/nacos.
Seata Setup
Use Seata version 1.5.0, which is a Spring Boot project. After downloading, modify application.yml (or resources/application.example.yml) to configure the registry, config center, and storage mode.
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
seata:
config:
type: file
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
namespace:
group: SEATA_GROUP
cluster: default
username: nacos
password: nacos
store:
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
user: root
password: root
min-conn: 5
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 100
max-wait: 5000
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/loginCreate the Seata database and execute the following DDL scripts to build the required tables.
-- 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_status_gmt_modified` (`status`,`gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 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=utf8mb4;
-- 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),
`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` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Distributed 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);Start Seata with seata-server. The console login uses seata/seata.
Project Setup
Business Background
The purchase flow involves three micro‑services:
Stock Service : Decrease inventory for a given product.
Order Service : Create an order based on the request.
Account Service : Deduct the user’s balance.
Architecture
Business Table Creation
-- t_account table
DROP TABLE IF EXISTS `t_account`;
CREATE TABLE `t_account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`amount` double(14,2) DEFAULT '0.00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `t_account` VALUES ('1','1','4000.00');
-- t_order table
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(255) DEFAULT NULL,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT '0',
`amount` double(14,2) DEFAULT '0.00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8;
-- t_stock table
DROP TABLE IF EXISTS `t_stock`;
CREATE TABLE `t_stock` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `t_stock` VALUES ('1','C201901140001','Water Cup','1000');
-- undo_log table (for Seata)
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS=1;Service Creation
Business Service
Introduce dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>Configure application.properties for the order service:
server.port=81
spring.application.name=order
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata_samples?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
mybatis-plus.mapper-locations=classpath:mapper/*.xml
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImplOrder creation endpoint:
@RequestMapping("/add")
public void add(String userId, String commodityCode, Integer count, BigDecimal amount) {
Order order = new Order();
order.setOrderNo(UUID.randomUUID().toString());
order.setUserId(userId);
order.setAmount(amount);
order.setCommodityCode(commodityCode);
order.setCount(count);
orderService.save(order);
}Aggregation Service
Define Feign clients for account, order, and stock services:
@FeignClient("account")
public interface AccountFeign {
@RequestMapping("/account/reduce")
void reduce(@RequestParam("userId") String userId, @RequestParam("amount") BigDecimal amount);
}
@FeignClient("order")
public interface OrderFeign {
@RequestMapping("/order/add")
void add(@RequestParam("userId") String userId,
@RequestParam("commodityCode") String commodityCode,
@RequestParam("count") Integer count,
@RequestParam("amount") BigDecimal amount);
}
@FeignClient("stock")
public interface StockFeign {
@RequestMapping("/stock/deduct")
void deduct(@RequestParam("commodityCode") String commodityCode,
@RequestParam("count") Integer count);
}Global transaction method:
@Autowired
private OrderFeign orderFeign;
@Autowired
private StockFeign stockFeign;
@Autowired
private AccountFeign accountFeign;
@GlobalTransactional
@RequestMapping("/toOrder")
public void toOrder(String userId, String commodityCode, Integer count, BigDecimal amount) {
accountFeign.reduce(userId, amount);
stockFeign.deduct(commodityCode, count);
orderFeign.add(userId, commodityCode, count, amount);
}Testing & Verification
Initial data: account balance 4000, stock 1000. Simulate a purchase of 2000 items costing 4000. Expected results after the request:
Account balance insufficient → global rollback.
Stock insufficient → exception triggers rollback.
Business service rolls back the global transaction.
Account balance restored to 4000.
Invoke the API:
http://127.0.0.1/business/toOrder?userId=1&commodityCode=C201901140001&count=2000&amount=4000
Observe logs of account and stock services and verify that the database tables remain unchanged.
Precautions
Seata 1.5 uses MySQL driver 5.x; replace it with mysql-connector-java-8.xx.jar in the libs directory.
Ensure compatibility among Spring Boot, Spring Cloud, and Spring Cloud Alibaba versions (see the compatibility matrix image).
Check Druid and driver version compatibility via the Druid repository documentation.
Code Repository
https://gitee.com/codeWBG/springcloud_alibaba
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.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
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.
