This is an automated email from the ASF dual-hosted git repository.
xingfudeshi pushed a commit to branch docusaurus
in repository https://gitbox.apache.org/repos/asf/incubator-seata-website.git
The following commit(s) were added to refs/heads/docusaurus by this push:
new afec627b694 optimize: reactor the quickstart.md (#1045)
afec627b694 is described below
commit afec627b6944a2e2ee7b272800fe05fdf08020d8
Author: jimin <[email protected]>
AuthorDate: Thu Dec 11 10:32:00 2025 +0800
optimize: reactor the quickstart.md (#1045)
---
.../current/user/quickstart.md | 399 +++++++++++++++-----
.../current/user/quickstart.md | 416 ++++++++++++++++-----
static/img/architecture.png | Bin 86886 -> 895011 bytes
static/img/solution.png | Bin 63215 -> 541683 bytes
4 files changed, 632 insertions(+), 183 deletions(-)
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/user/quickstart.md
b/i18n/en/docusaurus-plugin-content-docs/current/user/quickstart.md
index 9ef2ae57a79..901481df6ae 100644
--- a/i18n/en/docusaurus-plugin-content-docs/current/user/quickstart.md
+++ b/i18n/en/docusaurus-plugin-content-docs/current/user/quickstart.md
@@ -1,145 +1,195 @@
---
title: Quick Start
-keywords: [Seata]
-description: Let's begin with a Microservices example.
+keywords: [Seata, distributed transaction, microservices, quick start]
+description: Get started with Seata in 15 minutes using a microservices
example.
---
# Quick Start
-Let's begin with a Microservices example.
+This guide will help you quickly get started with Seata by walking through a
practical microservices example. You'll learn how to integrate Seata into your
distributed system and enable distributed transaction management.
-## Use case
+**Estimated Time:** 15-20 minutes
-A business logic for user purchasing commodities. The whole business logic is
powered by 3 microservices:
+## Prerequisites
-- Storage service: deduct storage count on given commodity.
-- Order service: create order according to purchase request.
-- Account service: debit the balance of user's account.
+Before you begin, ensure you have the following installed and configured:
-### Architecture
+- **Java Development Kit (JDK)**: Version 8 or higher
+- **Maven**: Version 3.x or higher
+- **MySQL**: Version 5.7 or higher with InnoDB engine
+- **Git**: For cloning the example repository
+
+## Scenario Overview
+
+We'll use a typical e-commerce scenario: **user purchasing commodities**. This
business logic involves three independent microservices:
+
+- **Account Service**: Manages user account balances and debits money during
purchases
+- **Order Service**: Creates and manages purchase orders
+- **Stock Service**: Tracks and deducts product inventory
+
+### The Distributed Transaction Challenge
+
+In a microservices architecture, each service has its own database. When a
user makes a purchase:
+
+1. The **Stock Service** deducts inventory
+2. The **Order Service** creates an order record
+3. The **Account Service** deducts the account balance
+
+These operations must either **all succeed or all fail together**. If the
account deduction fails (e.g., insufficient balance), the inventory and order
should be rolled back. This is the classic distributed transaction problem that
Seata solves.
+
+### Architecture Diagram

-### StorageService
+### Service Interfaces
-```java
-public interface StorageService {
+**StockService** - Inventory Management
+```java
+public interface StockService {
/**
- * deduct storage count
+ * Deduct stock count for a given commodity
+ * @param commodityCode The commodity identifier
+ * @param count The quantity to deduct
*/
void deduct(String commodityCode, int count);
}
```
-### OrderService
+**OrderService** - Order Management
```java
public interface OrderService {
-
/**
- * create order
+ * Create a new order
+ * @param userId The user identifier
+ * @param commodityCode The commodity identifier
+ * @param orderCount The order quantity
+ * @return The created order
*/
Order create(String userId, String commodityCode, int orderCount);
}
```
-### AccountService
+**AccountService** - Account Management
```java
public interface AccountService {
-
/**
- * debit balance of user's account
+ * Debit money from user's account
+ * @param userId The user identifier
+ * @param money The amount to debit
*/
void debit(String userId, int money);
}
```
-### Main business logic
+### Business Logic Implementation
+
+**Main Business Service** - Orchestrates the purchase flow
```java
public class BusinessServiceImpl implements BusinessService {
- private StorageService storageService;
-
+ private StockService stockService;
private OrderService orderService;
/**
- * purchase
+ * Execute purchase transaction
+ * This method coordinates calls to multiple microservices
*/
public void purchase(String userId, String commodityCode, int orderCount) {
-
- storageService.deduct(commodityCode, orderCount);
-
+ // Step 1: Deduct inventory
+ stockService.deduct(commodityCode, orderCount);
+
+ // Step 2: Create order (which also debits account)
orderService.create(userId, commodityCode, orderCount);
}
}
```
+**Order Service Implementation** - Creates order and debits account
+
```java
public class OrderServiceImpl implements OrderService {
private OrderDAO orderDAO;
-
private AccountService accountService;
public Order create(String userId, String commodityCode, int orderCount) {
-
+ // Calculate order amount
int orderMoney = calculate(commodityCode, orderCount);
+ // Step 1: Debit user account
accountService.debit(userId, orderMoney);
+ // Step 2: Create order record
Order order = new Order();
order.userId = userId;
order.commodityCode = commodityCode;
order.count = orderCount;
order.money = orderMoney;
- // INSERT INTO orders ...
+ // Persist order to database
return orderDAO.insert(order);
}
}
```
-## Distributed Transaction Solution with SEATA
+## Seata's Solution
-
+Seata provides a simple and elegant solution to manage distributed
transactions across these microservices.
-We just need an annotation `@GlobalTransactional` on business method:
+
-```java
+### How It Works
- @GlobalTransactional
- public void purchase(String userId, String commodityCode, int orderCount) {
- ......
- }
+With Seata, you only need to add a single annotation `@GlobalTransactional` to
your business method:
+
+```java
+@GlobalTransactional
+public void purchase(String userId, String commodityCode, int orderCount) {
+ // All operations within this method are now part of a global transaction
+ stockService.deduct(commodityCode, orderCount);
+ orderService.create(userId, commodityCode, orderCount);
+ // If any operation fails, all changes will be rolled back automatically
+}
```
-## Example powered by Dubbo + SEATA
+That's it! Seata handles:
+- **Coordination**: Managing the two-phase commit protocol
+- **Rollback**: Automatically reverting all changes if any service fails
+- **Consistency**: Ensuring data consistency across all microservices
-### Step 1: Setup database
+## Hands-On Example: Dubbo + Seata
-- Requirement: MySQL with InnoDB engine.
+Now let's set up a working example using Dubbo as the RPC framework and Seata
for distributed transaction management.
-**Note:** In fact, there should be 3 database for the 3 services in the
example use case. However, we can just create one database and configure 3 data
sources for simple.
+### Step 1: Set Up Database
-Modify Spring XML with the database URL/username/password you just created.
+**Requirements:**
+- MySQL 5.7+ with InnoDB engine
+- Create a database named `seata_example`
-dubbo-account-service.xml
-dubbo-order-service.xml
-dubbo-storage-service.xml
+**Configuration:**
-```xml
- <property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" />
- <property name="username" value="xxx" />
- <property name="password" value="xxx" />
+For simplicity, we'll use a single database with three separate tables. In
production, you would typically use separate databases for each service.
+
+Create a database:
+
+```sql
+CREATE DATABASE IF NOT EXISTS seata_example DEFAULT CHARSET utf8mb4;
+USE seata_example;
```
-### Step 2: Create UNDO_LOG table
+### Step 2: Create UNDO_LOG Table
+Seata's AT mode requires an `UNDO_LOG` table to store rollback information for
each service.
-`UNDO_LOG` table is required by SEATA AT mode. You can obtain the specified
version of the undo log SQL script from
[github](https://github.com/apache/incubator-seata/tree/2.x/script/client/at/db).
+**Why is this needed?**
+Seata uses this table to record data snapshots before and after changes,
enabling automatic rollback if the transaction fails.
+
+Execute the following SQL:
```sql
CREATE TABLE IF NOT EXISTS `undo_log`
@@ -152,18 +202,27 @@ CREATE TABLE IF NOT EXISTS `undo_log`
`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 = utf8mb4 COMMENT
='AT transaction mode undo table';
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4
+ COMMENT = 'AT transaction mode undo table';
+-- Add index for performance optimization
ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
-
```
-### Step 3: Create tables for example business
+:::tip
+You can find the latest SQL scripts for different databases in the [Seata
GitHub
repository](https://github.com/apache/incubator-seata/tree/2.x/script/client/at/db).
+:::
-```sql
+### Step 3: Create Business Tables
-DROP TABLE IF EXISTS `storage_tbl`;
-CREATE TABLE `storage_tbl` (
+Create tables for our three services:
+
+```sql
+-- Stock Service Table
+DROP TABLE IF EXISTS `stock_tbl`;
+CREATE TABLE `stock_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
@@ -171,7 +230,7 @@ CREATE TABLE `storage_tbl` (
UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
+-- Order Service Table
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@@ -182,7 +241,7 @@ CREATE TABLE `order_tbl` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
+-- Account Service Table
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@@ -192,52 +251,218 @@ CREATE TABLE `account_tbl` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
-### Step 4: Start Server
+**Insert test data:**
+
+```sql
+-- Add a test commodity with initial stock
+INSERT INTO stock_tbl (commodity_code, count) VALUES ('PRODUCT_001', 100);
+
+-- Add a test user with initial balance
+INSERT INTO account_tbl (user_id, money) VALUES ('USER_001', 1000);
+```
+
+### Step 4: Download and Start Seata Server
+
+**Download Seata Server:**
+
+1. Visit the [Seata Releases
page](https://github.com/apache/incubator-seata/releases)
+2. Download the latest version (e.g., `seata-server-2.x.x.zip`)
+3. Extract the archive
+
+**Start the Server:**
+
+For Linux/Mac:
+
+```bash
+cd seata-server-2.x.x
+sh ./bin/seata-server.sh -p 8091 -h 127.0.0.1 -m file
+```
+
+For Windows:
+
+```cmd
+cd seata-server-2.x.x
+bin\seata-server.bat -p 8091 -h 127.0.0.1 -m file
+```
+
+**Available Options:**
+
+| Option | Description | Default |
+|--------|-------------|---------|
+| `-h, --host` | The IP address exposed to registry center | 0.0.0.0 |
+| `-p, --port` | The port to listen on | 8091 |
+| `-m, --storeMode` | Transaction log store mode: `file` or `db` | file |
+
+**Verify Server Started:**
+
+You should see output like:
+
+```
+Server started, listen port: 8091
+```
+
+### Step 5: Run the Example Application
+
+**Clone the Example Repository:**
+
+```bash
+git clone https://github.com/apache/incubator-seata-samples.git
+cd incubator-seata-samples/at-sample/springboot-dubbo-seata
+```
+
+**Configure Database Connection:**
+
+Edit the configuration files for each service to use your database:
+
+- `account-service/src/main/resources/application.properties`
+- `order-service/src/main/resources/application.properties`
+- `stock-service/src/main/resources/application.properties`
+
+Update the database connection properties:
+
+```properties
+spring.datasource.url=jdbc:mysql://localhost:3306/seata_example
+spring.datasource.username=your_username
+spring.datasource.password=your_password
+```
+
+**Build and Start Services:**
+
+```bash
+# Build all services
+mvn clean install
+
+# Start each service in separate terminal windows:
+
+# Terminal 1 - Account Service
+cd account-service
+mvn spring-boot:run
+
+# Terminal 2 - Order Service
+cd order-service
+mvn spring-boot:run
+
+# Terminal 3 - Stock Service
+cd stock-service
+mvn spring-boot:run
+
+# Terminal 4 - Business Service
+cd business-service
+mvn spring-boot:run
+```
-- Download server package from
https://github.com/apache/incubator-seata/releases, unzip it.
+### Step 6: Test the Distributed Transaction
-```shell
-Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for
windows) [options]
- Options:
- --host, -h
- The address is expose to registration center and other service can
access seata-server via this ip.
- Default: 0.0.0.0
- --port, -p
- The port to listen.
- Default: 8091
- --storeMode, -m
- log store mode : file、db
- Default: file
- --help
+Once all services are running, you can test the distributed transaction:
-e.g.
+**Success Scenario:**
-sh seata-server.sh -p 8091 -h 127.0.0.1 -m file
+```bash
+curl -X POST http://localhost:8084/purchase \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "USER_001",
+ "commodityCode": "PRODUCT_001",
+ "orderCount": 1
+ }'
```
-### Step 5: Run example
+**Expected Result:**
+- Order created successfully
+- Stock deducted
+- Account balance reduced
+- Check database to verify all changes
-Go to samples repo:
[seata-samples/at-samples](https://github.com/apache/incubator-seata-samples/tree/master/at-sample),
and find a suitable dependency setup. Start `Account`, `Storage`, `Order`,
`Business` services accordingly.
+**Failure Scenario (Insufficient Balance):**
+
+Modify the account balance to be insufficient:
+
+```sql
+UPDATE account_tbl SET money = 1 WHERE user_id = 'USER_001';
+```
+
+Try purchasing again - the entire transaction should rollback:
+
+```bash
+curl -X POST http://localhost:8084/purchase \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "USER_001",
+ "commodityCode": "PRODUCT_001",
+ "orderCount": 1
+ }'
+```
+
+**Expected Result:**
+- Transaction fails
+- No order created
+- Stock remains unchanged
+- Account balance remains unchanged
+
+## Verification
+
+Check the Seata logs to see the transaction coordination:
+
+```bash
+tail -f seata-server-2.x.x/logs/seata-server.log
+```
+
+You should see logs showing:
+- Global transaction begin
+- Branch transaction registration
+- Two-phase commit or rollback
+
+## Next Steps
+
+Congratulations! You've successfully set up and run a distributed transaction
with Seata. Here's what you can explore next:
+
+- **[Transaction Modes](../dev/mode/at-mode)**: Learn about different
transaction modes (AT, TCC, SAGA, XA)
+- **[Microservices Integration](./microservice)**: Integrate Seata with
various microservices frameworks
+- **[Production Deployment](../ops/deploy-guide-beginner)**: Deploy Seata
Server in production environment
+- **[Performance Optimization](./performance)**: Optimize Seata for
high-performance scenarios
+- **[Configuration Guide](./configuration/)**: Configure Seata for different
scenarios
+
+## Troubleshooting
+
+**Services can't connect to Seata Server**
+- Verify Seata Server is running on port 8091
+- Check firewall settings
+- Ensure the host and port in service configuration match the Seata Server
+
+**Transaction not rolling back**
+- Verify `@GlobalTransactional` annotation is present
+- Check if `UNDO_LOG` table exists in all databases
+- Review application logs for errors
+
+**Database connection errors**
+- Verify database credentials in configuration files
+- Ensure MySQL is running and accessible
+- Check if the database and tables exist
+
+For more troubleshooting tips, visit the [FAQ section](../overview/faq) or
check out our [contribution guide](../developers/guide_dev).
## RocketMQ Integration to Seata
-Using RocketMQ as a participant in seata global transaction is simple,
-First, make sure you have introduced seata-all or springboot-starter of seata
dependency.
+Using RocketMQ as a participant in Seata global transaction is simple. First,
make sure you have introduced seata-all or springboot-starter of Seata
dependency.
+
+Create the producer by `SeataMQProducerFactory`, then send messages by
`SeataMQProducer`. Here is an example:
-Create the producer by `SeataMQProducerFactory`, then send messages by
`SeataMQProducer`. Here is an example:
```java
public class BusinessServiceImpl implements BusinessService {
private static final String NAME_SERVER = "127.0.0.1:9876";
private static final String PRODUCER_GROUP = "test-group";
private static final String TOPIC = "test-topic";
- private static SeataMQProducer producer=
SeataMQProducerFactory.createSingle(NAME_SERVER, PRODUCER_GROUP);
+ private static SeataMQProducer producer =
SeataMQProducerFactory.createSingle(NAME_SERVER, PRODUCER_GROUP);
public void purchase(String userId, String commodityCode, int orderCount) {
- producer.send(new Message(TOPIC,
"testMessage".getBytes(StandardCharsets.UTF_8)));
- //do something
+ producer.send(new Message(TOPIC,
"testMessage".getBytes(StandardCharsets.UTF_8)));
+ // do something
}
}
```
-The effect of this approach is that the production message acts as a
participant RM in the seata global transaction. When the 1st phase of the
global transaction is completed, the MQ message will be committed or rollback
based on the transaction 2nd phase’s request,
-the message will not be consumed until then.
-Note: If there is no xid in the current thread, the producer will degrade to a
normal send instead of sending a half-message.
+
+The effect of this approach is that the production message acts as a
participant RM in the Seata global transaction. When the 1st phase of the
global transaction is completed, the MQ message will be committed or rolled
back based on the transaction 2nd phase's request. The message will not be
consumed until then.
+
+:::note
+If there is no xid in the current thread, the producer will degrade to a
normal send instead of sending a half-message.
+:::
diff --git
a/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/quickstart.md
b/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/quickstart.md
index 03b0f6e74ce..56c88c8f34a 100644
--- a/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/quickstart.md
+++ b/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/quickstart.md
@@ -1,167 +1,226 @@
---
title: 快速启动
-keywords: [Seata]
-description: Seata 快速开始。
+keywords: [Seata, 分布式事务, 微服务, 快速开始]
+description: 通过一个微服务示例,15 分钟快速上手 Seata。
---
# 快速开始
-让我们从一个微服务示例开始。
+本指南将通过一个实际的微服务示例,帮助您快速上手 Seata。您将学习如何将 Seata 集成到分布式系统中,并实现分布式事务管理。
-## 用例
+**预计用时:** 15-20 分钟
-用户购买商品的业务逻辑。整个业务逻辑由 3 个微服务提供支持:
+## 前置条件
-- 仓储服务:对给定的商品扣除仓储数量。
-- 订单服务:根据采购需求创建订单。
-- 帐户服务:从用户帐户中扣除余额。
+开始之前,请确保您已安装并配置以下环境:
+
+- **Java 开发工具包(JDK)**:版本 8 或更高
+- **Maven**:版本 3.x 或更高
+- **MySQL**:版本 5.7 或更高,使用 InnoDB 引擎
+- **Git**:用于克隆示例代码仓库
+
+## 业务场景介绍
+
+我们将使用一个典型的电商场景:**用户购买商品**。该业务逻辑涉及三个独立的微服务:
+
+- **账户服务(Account Service)**:管理用户账户余额,购买时扣减账户金额
+- **订单服务(Order Service)**:创建和管理订单
+- **库存服务(Stock Service)**:管理商品库存,购买时扣减库存数量
+
+### 分布式事务的挑战
+
+在微服务架构中,每个服务都有自己独立的数据库。当用户购买商品时:
+
+1. **库存服务**扣减商品库存
+2. **订单服务**创建订单记录
+3. **账户服务**扣减账户余额
+
+这些操作必须**要么全部成功,要么全部失败**。如果账户扣款失败(例如余额不足),则库存和订单也应该回滚。这就是 Seata 要解决的典型分布式事务问题。
### 架构图
-
+
-### 仓储服务
+### 服务接口定义
-```java
-public interface StorageService {
+**StockService** - 库存管理
+```java
+public interface StockService {
/**
- * 扣除存储数量
+ * 扣减指定商品的库存数量
+ * @param commodityCode 商品编码
+ * @param count 扣减数量
*/
void deduct(String commodityCode, int count);
}
```
-### 订单服务
+**OrderService** - 订单管理
```java
public interface OrderService {
-
/**
- * 创建订单
+ * 创建新订单
+ * @param userId 用户ID
+ * @param commodityCode 商品编码
+ * @param orderCount 购买数量
+ * @return 创建的订单
*/
Order create(String userId, String commodityCode, int orderCount);
}
```
-### 帐户服务
+**AccountService** - 账户管理
```java
public interface AccountService {
-
/**
- * 从用户账户中借出
+ * 从用户账户扣款
+ * @param userId 用户ID
+ * @param money 扣款金额
*/
void debit(String userId, int money);
}
```
-### 主要业务逻辑
+### 业务逻辑实现
+
+**主业务服务** - 编排购买流程
```java
public class BusinessServiceImpl implements BusinessService {
- private StorageService storageService;
-
+ private StockService stockService;
private OrderService orderService;
/**
- * 采购
+ * 执行购买业务
+ * 该方法协调多个微服务的调用
*/
public void purchase(String userId, String commodityCode, int orderCount) {
+ // 步骤 1:扣减库存
+ stockService.deduct(commodityCode, orderCount);
- storageService.deduct(commodityCode, orderCount);
-
+ // 步骤 2:创建订单(同时会扣减账户余额)
orderService.create(userId, commodityCode, orderCount);
}
}
```
+**订单服务实现** - 创建订单并扣款
+
```java
public class OrderServiceImpl implements OrderService {
private OrderDAO orderDAO;
-
private AccountService accountService;
public Order create(String userId, String commodityCode, int orderCount) {
-
+ // 计算订单金额
int orderMoney = calculate(commodityCode, orderCount);
+ // 步骤 1:扣减用户账户余额
accountService.debit(userId, orderMoney);
+ // 步骤 2:创建订单记录
Order order = new Order();
order.userId = userId;
order.commodityCode = commodityCode;
order.count = orderCount;
order.money = orderMoney;
- // INSERT INTO orders ...
+ // 持久化订单到数据库
return orderDAO.insert(order);
}
}
```
-## SEATA 的分布式交易解决方案
+## Seata 的解决方案
-
-我们只需要使用一个 `@GlobalTransactional` 注解在业务方法上:
+Seata 提供了简单优雅的解决方案来管理跨多个微服务的分布式事务。
-```java
+
- @GlobalTransactional
- public void purchase(String userId, String commodityCode, int orderCount) {
- ......
- }
+### 工作原理
+
+使用 Seata,您只需要在业务方法上添加一个 `@GlobalTransactional` 注解:
+
+```java
+@GlobalTransactional
+public void purchase(String userId, String commodityCode, int orderCount) {
+ // 该方法内的所有操作现在都是全局事务的一部分
+ stockService.deduct(commodityCode, orderCount);
+ orderService.create(userId, commodityCode, orderCount);
+ // 如果任何操作失败,所有更改都将自动回滚
+}
```
-## 由 Dubbo + SEATA 提供支持的示例
+就是这么简单!Seata 会帮您处理:
+- **协调**:管理两阶段提交协议
+- **回滚**:如果任何服务失败,自动回滚所有更改
+- **一致性**:确保所有微服务之间的数据一致性
-### 步骤 1:建立数据库
+## 实战示例:Dubbo + Seata
-- 要求:具有 InnoDB 引擎的 MySQL。
+现在让我们使用 Dubbo 作为 RPC 框架,Seata 作为分布式事务管理器,搭建一个可运行的示例。
-**注意:** 实际上,在示例用例中,这 3 个服务应该有 3 个数据库。 但是,为了简单起见,我们只创建一个数据库并配置 3 个数据源。
+### 步骤 1:配置数据库
-使用您刚创建的数据库 URL/username/password 修改 Spring XML。
+**环境要求:**
+- MySQL 5.7+ 使用 InnoDB 引擎
+- 创建名为 `seata_example` 的数据库
-dubbo-account-service.xml
-dubbo-order-service.xml
-dubbo-storage-service.xml
+**创建数据库:**
-```xml
- <property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" />
- <property name="username" value="xxx" />
- <property name="password" value="xxx" />
+为了简化示例,我们使用一个数据库和三张独立的表。在生产环境中,通常每个服务会使用独立的数据库。
+
+```sql
+CREATE DATABASE IF NOT EXISTS seata_example DEFAULT CHARSET utf8mb4;
+USE seata_example;
```
### 步骤 2:创建 UNDO_LOG 表
-SEATA AT 模式需要 `UNDO_LOG` 表。你可以通过 github 获取到指定版本的undo log SQL
[脚本](https://github.com/apache/incubator-seata/tree/2.x/script/client/at/db).
+Seata 的 AT 模式需要 `UNDO_LOG` 表来存储每个服务的回滚信息。
+
+**为什么需要这张表?**
+Seata 使用此表记录数据变更前后的快照,以便在事务失败时能够自动回滚。
+
+执行以下 SQL:
```sql
--- 注意此处0.3.0+ 增加唯一索引 ux_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,
- `ext` varchar(100) DEFAULT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
+CREATE TABLE IF NOT EXISTS `undo_log`
+(
+ `branch_id` BIGINT NOT NULL COMMENT '分支事务ID',
+ `xid` VARCHAR(128) NOT NULL COMMENT '全局事务ID',
+ `context` VARCHAR(128) NOT NULL COMMENT 'undo_log 上下文,如序列化配置',
+ `rollback_info` LONGBLOB NOT NULL COMMENT '回滚信息',
+ `log_status` INT(11) NOT NULL COMMENT '0:正常状态,1:防御状态',
+ `log_created` DATETIME(6) NOT NULL COMMENT '创建时间',
+ `log_modified` DATETIME(6) NOT NULL COMMENT '修改时间',
+ UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4
+ COMMENT = 'AT 事务模式 undo 日志表';
+
+-- 添加索引以优化性能
+ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
```
-### 步骤 3:为示例业务创建表
+:::tip
+您可以在 [Seata GitHub
仓库](https://github.com/apache/incubator-seata/tree/2.x/script/client/at/db)
中找到适用于不同数据库的最新 SQL 脚本。
+:::
-```sql
+### 步骤 3:创建业务表
-DROP TABLE IF EXISTS `storage_tbl`;
-CREATE TABLE `storage_tbl` (
+为三个服务创建对应的业务表:
+
+```sql
+-- 库存服务表
+DROP TABLE IF EXISTS `stock_tbl`;
+CREATE TABLE `stock_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
@@ -169,7 +228,7 @@ CREATE TABLE `storage_tbl` (
UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
+-- 订单服务表
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@@ -180,7 +239,7 @@ CREATE TABLE `order_tbl` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
+-- 账户服务表
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@@ -190,53 +249,218 @@ CREATE TABLE `account_tbl` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
-### 步骤 4: 启动服务
+**插入测试数据:**
+
+```sql
+-- 添加测试商品和初始库存
+INSERT INTO stock_tbl (commodity_code, count) VALUES ('PRODUCT_001', 100);
+
+-- 添加测试用户和初始余额
+INSERT INTO account_tbl (user_id, money) VALUES ('USER_001', 1000);
+```
+
+### 步骤 4:下载并启动 Seata Server
-- 从
[https://github.com/apache/incubator-seata/releases](https://github.com/apache/incubator-seata/releases),下载服务器软件包,将其解压缩。
+**下载 Seata Server:**
-```shell
-Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for
windows) [options]
- Options:
- --host, -h
- The address is expose to registration center and other service can
access seata-server via this ip
- Default: 0.0.0.0
- --port, -p
- The port to listen.
- Default: 8091
- --storeMode, -m
- log store mode : file、db
- Default: file
- --help
+1. 访问 [Seata Releases 页面](https://github.com/apache/incubator-seata/releases)
+2. 下载最新版本(例如 `seata-server-2.x.x.zip`)
+3. 解压压缩包
-e.g.
+**启动服务器:**
-sh seata-server.sh -p 8091 -h 127.0.0.1 -m file
+Linux/Mac 系统:
+
+```bash
+cd seata-server-2.x.x
+sh ./bin/seata-server.sh -p 8091 -h 127.0.0.1 -m file
```
-### 步骤 5: 运行示例
+Windows 系统:
-示例仓库:
[seata-samples/at-samples](https://github.com/apache/incubator-seata-samples/tree/master/at-sample)。找到合适的依赖项设置,按顺序启动
`Account`, `Storage`, `Order`, `Business` 服务。
+```cmd
+cd seata-server-2.x.x
+bin\seata-server.bat -p 8091 -h 127.0.0.1 -m file
+```
+**可用参数说明:**
-## RocketMQ 接入 Seata
+| 参数 | 说明 | 默认值 |
+|------|------|--------|
+| `-h, --host` | 暴露给注册中心的 IP 地址 | 0.0.0.0 |
+| `-p, --port` | 监听端口 | 8091 |
+| `-m, --storeMode` | 事务日志存储模式:`file` 或 `db` | file |
-使用RocketMQ作为Seata分布式事务的参与者很简单,先确保已经引入了seata-all或者seata的springboot-starter依赖。
+**验证服务器启动成功:**
-然后通过`SeataMQProducerFactory`创建生产者,然后通过 `SeataMQProducer` 可以直接使用 RocketMQ
发送消息。以下是一个例子:
+您应该看到类似以下的输出:
+```
+Server started, listen port: 8091
+```
+
+### 步骤 5:运行示例应用
+
+**克隆示例代码仓库:**
+
+```bash
+git clone https://github.com/apache/incubator-seata-samples.git
+cd incubator-seata-samples/at-sample/springboot-dubbo-seata
+```
+
+**配置数据库连接:**
+
+编辑每个服务的配置文件以使用您的数据库:
+
+- `account-service/src/main/resources/application.properties`
+- `order-service/src/main/resources/application.properties`
+- `stock-service/src/main/resources/application.properties`
+
+更新数据库连接配置:
+
+```properties
+spring.datasource.url=jdbc:mysql://localhost:3306/seata_example
+spring.datasource.username=您的数据库用户名
+spring.datasource.password=您的数据库密码
+```
+
+**构建并启动服务:**
+
+```bash
+# 构建所有服务
+mvn clean install
+
+# 在不同的终端窗口启动各个服务:
+
+# 终端 1 - 账户服务
+cd account-service
+mvn spring-boot:run
+
+# 终端 2 - 订单服务
+cd order-service
+mvn spring-boot:run
+
+# 终端 3 - 库存服务
+cd stock-service
+mvn spring-boot:run
+
+# 终端 4 - 业务服务
+cd business-service
+mvn spring-boot:run
+```
+
+### 步骤 6:测试分布式事务
+
+所有服务启动后,您可以测试分布式事务:
+
+**成功场景:**
+
+```bash
+curl -X POST http://localhost:8084/purchase \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "USER_001",
+ "commodityCode": "PRODUCT_001",
+ "orderCount": 1
+ }'
+```
+
+**预期结果:**
+- 订单创建成功
+- 库存扣减成功
+- 账户余额减少
+- 检查数据库验证所有更改
+
+**失败场景(余额不足):**
+
+修改账户余额为不足的金额:
+
+```sql
+UPDATE account_tbl SET money = 1 WHERE user_id = 'USER_001';
+```
+
+再次尝试购买 - 整个事务应该回滚:
+
+```bash
+curl -X POST http://localhost:8084/purchase \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "USER_001",
+ "commodityCode": "PRODUCT_001",
+ "orderCount": 1
+ }'
+```
+
+**预期结果:**
+- 事务失败
+- 没有创建订单
+- 库存数量保持不变
+- 账户余额保持不变
+
+## 验证
+
+查看 Seata 日志以观察事务协调过程:
+
+```bash
+tail -f seata-server-2.x.x/logs/seata-server.log
+```
+
+您应该看到显示以下内容的日志:
+- 全局事务开始
+- 分支事务注册
+- 两阶段提交或回滚
+
+## 下一步
+
+恭喜!您已经成功使用 Seata 搭建并运行了分布式事务。接下来您可以探索:
+
+- **[事务模式](../dev/mode/at-mode)**:了解不同的事务模式(AT、TCC、SAGA、XA)
+- **[微服务集成](./microservice)**:将 Seata 集成到各种微服务框架
+- **[生产部署](../ops/deploy-guide-beginner)**:在生产环境部署 Seata Server
+- **[性能优化](./performance)**:针对高性能场景优化 Seata
+- **[配置指南](./configuration/)**:针对不同场景配置 Seata
+
+## 故障排查
+
+**服务无法连接到 Seata Server**
+- 验证 Seata Server 是否在 8091 端口运行
+- 检查防火墙设置
+- 确保服务配置中的主机和端口与 Seata Server 匹配
+
+**事务没有回滚**
+- 验证是否添加了 `@GlobalTransactional` 注解
+- 检查所有数据库中是否存在 `UNDO_LOG` 表
+- 查看应用日志中的错误信息
+
+**数据库连接错误**
+- 验证配置文件中的数据库凭据
+- 确保 MySQL 正在运行且可访问
+- 检查数据库和表是否存在
+
+更多故障排查技巧,请访问 [常见问题](../overview/faq) 或查看我们的 [贡献指南](../developers/guide_dev)。
+
+## RocketMQ 接入 Seata
+
+使用 RocketMQ 作为 Seata 分布式事务的参与者非常简单。首先,确保已经引入了 seata-all 或者 seata 的
springboot-starter 依赖。
+
+通过 `SeataMQProducerFactory` 创建生产者,然后通过 `SeataMQProducer` 可以直接使用 RocketMQ
发送消息。以下是一个示例:
```java
public class BusinessServiceImpl implements BusinessService {
private static final String NAME_SERVER = "127.0.0.1:9876";
private static final String PRODUCER_GROUP = "test-group";
private static final String TOPIC = "test-topic";
- private static SeataMQProducer producer=
SeataMQProducerFactory.createSingle(NAME_SERVER, PRODUCER_GROUP);
+ private static SeataMQProducer producer =
SeataMQProducerFactory.createSingle(NAME_SERVER, PRODUCER_GROUP);
public void purchase(String userId, String commodityCode, int orderCount) {
- producer.send(new Message(TOPIC,
"testMessage".getBytes(StandardCharsets.UTF_8)));
- //do something
+ producer.send(new Message(TOPIC,
"testMessage".getBytes(StandardCharsets.UTF_8)));
+ // 执行其他业务逻辑
}
}
```
-这样达到的效果是:生产消息作为Seata分布式事务的参与者RM,当全局事务的一阶段完成,这个MQ消息会根据二阶段要求commit/rollback进行消息的提交或撤回,在此之前消息不会被消费。
-注: 当前线程中如果没有xid,该producer会退化为普通的send,而不是发送半消息
+
+这样达到的效果是:生产消息作为 Seata 分布式事务的参与者 RM,当全局事务的一阶段完成,这个 MQ 消息会根据二阶段要求
commit/rollback 进行消息的提交或撤回,在此之前消息不会被消费。
+
+:::note
+如果当前线程中没有 xid,该 producer 会退化为普通的 send,而不是发送半消息。
+:::
diff --git a/static/img/architecture.png b/static/img/architecture.png
index fc89667263d..237b4b1883a 100644
Binary files a/static/img/architecture.png and b/static/img/architecture.png
differ
diff --git a/static/img/solution.png b/static/img/solution.png
index 5d2126cd6bc..5df3a3a62fd 100644
Binary files a/static/img/solution.png and b/static/img/solution.png differ
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]