分布式事務(wù)Seata學(xué)習(xí)筆記

一材诽、概述

在微服務(wù)架構(gòu)下底挫,雖然我們會(huì)盡量避免分布式事務(wù),但是只要業(yè)務(wù)復(fù)雜的情況下這是一個(gè)繞不開的問題脸侥,如何保證業(yè)務(wù)數(shù)據(jù)一致性呢建邓?本文主要介紹同步場景下使用Seata的AT模式來解決一致性問題。
Seata 是阿里開源的一款開源的分布式事務(wù)解決方案睁枕,致力于提供高性能和簡單易用的分布式事務(wù)服務(wù)涝缝。Seata 將為用戶提供了 AT、TCC譬重、SAGA 和 XA 事務(wù)模式拒逮,為用戶打造一站式的分布式解決方案

二、Seata簡介

整體事務(wù)邏輯是基于 兩階段提交 的模型臀规,核心概念包括以下3個(gè)角色:

  • TM:事務(wù)的發(fā)起者滩援。用來告訴 TC,全局事務(wù)的開始塔嬉,提交玩徊,回滾。
  • RM:具體的事務(wù)資源谨究,每一個(gè) RM 都會(huì)作為一個(gè)分支事務(wù)注冊(cè)在 TC恩袱。
  • TC:事務(wù)的協(xié)調(diào)者seata-server,用于接收我們的事務(wù)的注冊(cè)胶哲,提交和回滾畔塔。

根據(jù)兩階段行為模式的不同,我們將分支事務(wù)劃分為Automatic (Branch) Transaction ModeManual (Branch) Transaction Mode

2.1. AT模式

該模式適合的場景:

  • 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫鸯屿。
  • Java 應(yīng)用澈吨,通過 JDBC 訪問數(shù)據(jù)庫。
  • 一階段 prepare 行為:在本地事務(wù)中寄摆,一并提交業(yè)務(wù)數(shù)據(jù)更新和相應(yīng)回滾日志記錄谅辣。
  • 二階段 commit 行為:馬上成功結(jié)束,自動(dòng) 異步批量清理回滾日志婶恼。
  • 二階段 rollback 行為:通過回滾日志桑阶,自動(dòng) 生成補(bǔ)償操作柏副,完成數(shù)據(jù)回滾。

    一個(gè)典型的分布式事務(wù)過程:
  • TM 向 TC 申請(qǐng)開啟一個(gè)全局事務(wù)蚣录,全局事務(wù)創(chuàng)建成功并生成一個(gè)全局唯一的 XID搓扯。
  • XID 在微服務(wù)調(diào)用鏈路的上下文中傳播。
  • RM 向 TC 注冊(cè)分支事務(wù)包归,將其納入 XID 對(duì)應(yīng)全局事務(wù)的管轄。
  • TM 向 TC 發(fā)起針對(duì) XID 的全局提交或回滾決議铅歼。
  • TC 調(diào)度 XID 下管轄的全部分支事務(wù)完成提交或回滾請(qǐng)求公壤。

2.2. MT模式

該模式邏輯類似TCC,需要 自定義實(shí)現(xiàn) prepare椎椰、commit和rollback的邏輯厦幅,適合 非關(guān)系型數(shù)據(jù)庫 的場景


TCC(MT) 模式,不依賴于底層數(shù)據(jù)資源的事務(wù)支持:

  • 一階段 prepare 行為:調(diào)用 自定義 的 prepare 邏輯慨飘。
  • 二階段 commit 行為:調(diào)用 自定義 的 commit 邏輯确憨。
  • 二階段 rollback 行為:調(diào)用 自定義 的 rollback 邏輯。

所謂 TCC 模式瓤的,是指支持把 自定義 的分支事務(wù)納入到全局事務(wù)的管理中休弃。

三、示例版本說明

  • Seata 1.3.0
  • Nacos 1.4.0
  • SpringBoot 2.2.10.RELEASE
  • SpringCloud Hoxton.SR8
  • SpringCloudAlibaba 2.2.3.RELEASE

啟動(dòng)Nacos

  • 下載地址
  • 創(chuàng)建數(shù)據(jù)庫nacos-config

sql腳本文件在nacos-server-1.4.0\nacos\conf目錄下nacos-mysql.sql

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = config_info   */
/******************************************/
CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '內(nèi)容',
  `gmt_modified` datetime NOT NULL COMMENT '修改時(shí)間',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租戶字段';


/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID圈膏,空字符表示整個(gè)集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額塔猾,0表示使用默認(rèn)值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個(gè)配置大小上限,單位為字節(jié)稽坤,0表示使用默認(rèn)值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個(gè)數(shù)丈甸,,0表示使用默認(rèn)值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個(gè)聚合數(shù)據(jù)的子配置大小上限尿褪,單位為字節(jié)睦擂,0表示使用默認(rèn)值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數(shù)量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';

/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(64) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `src_user` text,
  `src_ip` varchar(20) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租戶改造';


/******************************************/
/*   數(shù)據(jù)庫全名 = nacos_config   */
/*   表名稱 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額杖玲,0表示使用默認(rèn)值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個(gè)配置大小上限顿仇,單位為字節(jié),0表示使用默認(rèn)值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個(gè)數(shù)',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個(gè)聚合數(shù)據(jù)的子配置大小上限摆马,單位為字節(jié)夺欲,0表示使用默認(rèn)值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數(shù)量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租戶容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '創(chuàng)建時(shí)間',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

CREATE TABLE `users` (
    `username` varchar(50) NOT NULL PRIMARY KEY,
    `password` varchar(500) NOT NULL,
    `enabled` boolean NOT NULL
);

CREATE TABLE `roles` (
    `username` varchar(50) NOT NULL,
    `role` varchar(50) NOT NULL,
    UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);

CREATE TABLE `permissions` (
    `role` varchar(50) NOT NULL,
    `resource` varchar(255) NOT NULL,
    `action` varchar(8) NOT NULL,
    UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

  • 修改/conf/application.properties配置文件中的數(shù)據(jù)源信息。其他配置可以參考Nacos文檔
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=root
  • 啟動(dòng)Nacos

單機(jī)模式

startup.cmd -m standalone

啟動(dòng)成功后訪問http://127.0.0.1:8848/nacos用戶名今膊、密碼均為nacos

啟動(dòng)Seata-Server

下載Seata

seata-server-1.3.0下載鏈接

seata-1.3.0 源碼

初始化數(shù)據(jù)庫

  • 創(chuàng)建數(shù)據(jù)庫seata_config
  • 初始化腳本如下些阅,在1.0及以下版本中提供(大坑)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for branch_table
-- ----------------------------
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table`  (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `status` tinyint(4) NULL DEFAULT NULL,
  `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime(6) NULL DEFAULT NULL,
  `gmt_modified` datetime(6) NULL DEFAULT NULL,
  PRIMARY KEY (`branch_id`) USING BTREE,
  INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of branch_table
-- ----------------------------

-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table`  (
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `timeout` int(11) NULL DEFAULT NULL,
  `begin_time` bigint(20) NULL DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime(0) NULL DEFAULT NULL,
  `gmt_modified` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`xid`) USING BTREE,
  INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
  INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of global_table
-- ----------------------------

-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table`  (
  `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime(0) NULL DEFAULT NULL,
  `gmt_modified` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`row_key`) USING BTREE,
  INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of lock_table
-- ----------------------------

SET FOREIGN_KEY_CHECKS = 1;

同步配置至Nacos

在seata-1.3.0源碼中seata\script\config-center\config.txt 復(fù)制到解壓后的seata包中并修改如下配置

service.vgroupMapping.my_test_tx_group=default
store.mode=db
store.db.url=jdbc:mysql://127.0.0.1:3306/seata_config?useUnicode=true
store.db.user=root
store.db.password=root

其中my_test_tx_group是事物分組名稱,可以隨意修改但要注意必須與工程中的配置相同

復(fù)制seata-1.3.0源碼目錄seata\script\config-center\nacos\nacos-config.sh文件至seata解壓包conf\script目錄下斑唬,并運(yùn)行 sh nacos-config.sh 127.0.0.1

注意:這里因?yàn)槭莝h腳本市埋,可以使用cmder或git的bash命令窗口,并且腳本文件必須在config.txt文件的子文件夾中

成功后命令行輸出所有同步至nacos中的配置信息黎泣,并輸出init nacos config finished, please start seata-server表示同步配置成功

打開配置中心也可以看到配置信息


  • 運(yùn)行seata-server.bat | seata-server.sh啟動(dòng)seata 觀察控制臺(tái)監(jiān)聽在8091端口

SpringCloudAlibaba集成Seata

    <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    </dependency>

參考官網(wǎng)實(shí)例案例和demo,版本差異稍作修改

  • 初始化業(yè)務(wù)數(shù)據(jù)庫seata_demo缤谎,在seata官方示例demo中有提供sql腳本
-- 創(chuàng)建 order庫抒倚、業(yè)務(wù)表、undo_log表
create database seata_order;
use seata_order;

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;

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;


-- 創(chuàng)建 storage庫坷澡、業(yè)務(wù)表托呕、undo_log表
create database seata_storage;
use seata_storage;

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;

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;

-- 初始化庫存模擬數(shù)據(jù)
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (1, 'product-1', 9999999);
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (2, 'product-2', 0);
  • application.yml配置如下
seata:
  tx-service-group: my_test_tx_group 
  config:
    type: nacos
    nacos:
      serverAddr: ${spring.cloud.nacos.server-addr}
      group: SEATA_GROUP
      username: nacos
      password: nacos
  registry:
    type: nacos
    nacos:
      server-addr: ${spring.cloud.nacos.server-addr}
      group: SEATA_GROUP
      username: nacos
      password: nacos

注意:配置中tx-service-group必須和config.txt中的vgroupMapping配置一致(已同步至Nacos配置中心)

  • 分別運(yùn)行business-servicestorage-service频敛、order-service项郊、account-service

啟動(dòng)成功后調(diào)用下單成功和異常接口

觀察控制臺(tái)日志可以看到各服務(wù)的事務(wù)id如下

biz: 87904197444374528 #bisness-service(TM)向TC申請(qǐng)的全局事物ID XID
    storage: 87904197503094784  #storage-service 分支事物id
    order  : 87904197620535297  #order-service 分支事物id
        account: 87904197729587201  #account-service 分支事物id

當(dāng)出現(xiàn)異常時(shí)TC會(huì)通知所有RM回滾事務(wù)

PhaseTwo_Rollbacked

參考文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市斟赚,隨后出現(xiàn)的幾起案子着降,更是在濱河造成了極大的恐慌,老刑警劉巖拗军,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件任洞,死亡現(xiàn)場離奇詭異,居然都是意外死亡发侵,警方通過查閱死者的電腦和手機(jī)交掏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刃鳄,“玉大人耀销,你說我怎么就攤上這事〔簦” “怎么了熊尉?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掌腰。 經(jīng)常有香客問我狰住,道長,這世上最難降的妖魔是什么齿梁? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任催植,我火速辦了婚禮,結(jié)果婚禮上勺择,老公的妹妹穿的比我還像新娘创南。我一直安慰自己,他們只是感情好省核,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布稿辙。 她就那樣靜靜地躺著,像睡著了一般气忠。 火紅的嫁衣襯著肌膚如雪邻储。 梳的紋絲不亂的頭發(fā)上赋咽,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音吨娜,去河邊找鬼脓匿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宦赠,可吹牛的內(nèi)容都是我干的陪毡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼勾扭,長吁一口氣:“原來是場噩夢啊……” “哼毡琉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尺借,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎精拟,沒想到半個(gè)月后燎斩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜂绎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年栅表,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片师枣。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怪瓶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出践美,到底是詐尸還是另有隱情洗贰,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布陨倡,位于F島的核電站敛滋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏兴革。R本人自食惡果不足惜绎晃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杂曲。 院中可真熱鬧庶艾,春花似錦、人聲如沸擎勘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棚饵。三九已至述召,卻和暖如春朱转,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背积暖。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工藤为, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夺刑。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓缅疟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遍愿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子存淫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容