Quick start
Let's start with a microservice example. The official example uses the AT mode in seata distributed transaction, that is, the example is based on:
- Based on a relational database that supports local ACID transactions.
- Java application, accessing database through JDBC..
Use case
Business logic for users to purchase goods. The whole business logic is supported by three micro services:
- Warehousing service: deduct the warehousing quantity for a given commodity.
- Order service: create orders according to purchase requirements.
- Account service: deduct the balance from the user account.
Architecture diagram
Warehousing service
public interface StorageService { /** * Deduct storage quantity */ void deduct(String commodityCode, int count); }
Order service
public interface OrderService { /** * Create order */ Order create(String userId, String commodityCode, int orderCount); }
Account services
public interface AccountService { /** * Lending from user account */ void debit(String userId, int money); }
Main business logic
public class BusinessServiceImpl implements BusinessService { private StorageService storageService; private OrderService orderService; /** * purchase */ public void purchase(String userId, String commodityCode, int orderCount) { storageService.deduct(commodityCode, orderCount); orderService.create(userId, commodityCode, orderCount); } } 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); accountService.debit(userId, orderMoney); Order order = new Order(); order.userId = userId; order.commodityCode = commodityCode; order.count = orderCount; order.money = orderMoney; // INSERT INTO orders ... return orderDAO.insert(order); } }
SEATA's distributed transaction solution
We only need to use a @ GlobalTransactional annotation to realize the distributed transaction function on the business method.
Examples supported by Dubbo + SEATA
Step 1: establish database
- Requirement: MySQL with InnoDB engine.
Note: in fact, in the example use case, these three services should have three databases. However, for simplicity, we can only create one database and configure three data sources.
Modify the Spring XML using the database URL/username/password you just created.
dubbo-account-service.xml dubbo-order-service.xml dubbo-storage-service.xml <property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" /> <property name="username" value="xxx" /> <property name="password" value="xxx" />
Step 2: create UNDO_LOG table
SEATA AT mode requires {UNDO_LOG} table
-- Note here 0.3.0+ Add unique index 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;
Step 3: create a table for the sample business
DROP TABLE IF EXISTS `storage_tbl`; CREATE TABLE `storage_tbl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `commodity_code` varchar(255) DEFAULT NULL, `count` int(11) DEFAULT 0, PRIMARY KEY (`id`), 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, `user_id` varchar(255) DEFAULT NULL, `commodity_code` varchar(255) DEFAULT NULL, `count` int(11) DEFAULT 0, `money` int(11) DEFAULT 0, 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, `user_id` varchar(255) DEFAULT NULL, `money` int(11) DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Step 4: start the service
There are two main ways to start a service:
First, go to the official website to download the software package and start it with a script
The second is to directly download the seata source code and find the server service.
Let's take the source startup server as an example:
Found server Java this file, run directly.
The default port of the official example service of seata is 8091 and the storage method is file.
Step 5: run the example
Example warehouse: seata-samples
- Start DubboAccountServiceStarter
- Start DubboStorageServiceStarter
- Start DubboOrderServiceStarter
- Run dubbobusiness tester for demo test
In the dubbobusiness tester example, we let the program sleep for 10 seconds and then throw an exception. During this period, we observe whether the data in the database can be rolled back.
@Override @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") public void purchase(String userId, String commodityCode, int orderCount) { LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); storageService.deduct(commodityCode, orderCount); orderService.create(userId, commodityCode, orderCount); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } throw new RuntimeException("xxx"); }