让我们从一个微服务示例开始。
用户购买商品的业务逻辑。整个业务逻辑由 3 个微服务提供支持:
public interface StorageService { /** * 扣除存储数量 */ void deduct(String commodityCode, int count); }
public interface OrderService { /** * 创建订单 */ Order create(String userId, String commodityCode, int orderCount); }
public interface AccountService { /** * 从用户账户中借出 */ void debit(String userId, int money); }
public class BusinessServiceImpl implements BusinessService { private StorageService storageService; private OrderService orderService; /** * 采购 */ 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); } }
 我们只需要使用一个 
@GlobalTransactional 注解在业务方法上:
@GlobalTransactional public void purchase(String userId, String commodityCode, int orderCount) { ...... }
注意: 实际上,在示例用例中,这 3 个服务应该有 3 个数据库。 但是,为了简单起见,我们只创建一个数据库并配置 3 个数据源。
使用您刚创建的数据库 URL/username/password 修改 Spring XML。
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" />
SEATA AT 模式需要 UNDO_LOG 表。你可以通过 github 获取到指定版本的undo log SQL 脚本.
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 = utf8mb4 COMMENT ='AT transaction mode undo table'; ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
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;
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 e.g. sh seata-server.sh -p 8091 -h 127.0.0.1 -m file
示例仓库: seata-samples
TBD: 运行演示应用程序的脚本