Seata分布式事務(wù)中間件Sample演示

Seata(Simple Extensible Autonomous Transaction Architecture)是2019 年 1 月份螞蟻金服和阿里巴巴共同開源的 分布式事務(wù) 解決方案。以 高效 并且對(duì)業(yè)務(wù) 0 侵入 的方式病往,解決 微服務(wù) 場(chǎng)景下面臨的分布式事務(wù)問(wèn)題胚想。

產(chǎn)生背景

隨著業(yè)務(wù)數(shù)據(jù)規(guī)模的快速發(fā)展偶宫,數(shù)據(jù)量越來(lái)越大卒暂,原有的單庫(kù)單表模式逐漸成為瓶頸饶号。這時(shí)需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行了水平拆分,將原單庫(kù)單表拆分成數(shù)據(jù)庫(kù)分片咳燕。分庫(kù)分表之后勿决,原來(lái)在一個(gè)數(shù)據(jù)庫(kù)上就能完成的寫操作,可能就會(huì)跨多個(gè)數(shù)據(jù)庫(kù)招盲,這就產(chǎn)生了跨數(shù)據(jù)庫(kù)事務(wù)問(wèn)題低缩。

同時(shí)系統(tǒng)的訪問(wèn)量和業(yè)務(wù)復(fù)雜程度也在快速增長(zhǎng),單體系統(tǒng)架構(gòu)逐漸成為業(yè)務(wù)發(fā)展瓶頸曹货,將單業(yè)務(wù)系統(tǒng)拆分成多個(gè)業(yè)務(wù)系統(tǒng)咆繁,降低了各系統(tǒng)之間的耦合度,使不同的業(yè)務(wù)系統(tǒng)專注于自身業(yè)務(wù)顶籽,更有利于業(yè)務(wù)的發(fā)展和系統(tǒng)容量的伸縮玩般。如何保證多個(gè)服務(wù)間的數(shù)據(jù)一致性成為一個(gè)難題。

Seata產(chǎn)品模塊

產(chǎn)品模塊

如上圖所示礼饱,Seata 中有三大模塊坏为,分別是 TM、RM 和 TC镊绪。 其中 TM 和 RM 是作為 Seata 的客戶端與業(yè)務(wù)系統(tǒng)集成在一起匀伏,TC 作為 Seata 的服務(wù)端獨(dú)立部署。

在 Seata 中蝴韭,分布式事務(wù)的執(zhí)行流程:

  • TM 開啟分布式事務(wù)(TM 向 TC 注冊(cè)全局事務(wù)記錄)够颠;
  • 按業(yè)務(wù)場(chǎng)景,編排數(shù)據(jù)庫(kù)榄鉴、服務(wù)等事務(wù)內(nèi)資源(RM 向 TC 匯報(bào)資源準(zhǔn)備狀態(tài) )履磨;
  • TM 結(jié)束分布式事務(wù),事務(wù)一階段結(jié)束(TM 通知 TC 提交/回滾分布式事務(wù))牢硅;
  • TC 匯總事務(wù)信息蹬耘,決定分布式事務(wù)是提交還是回滾;
  • TC 通知所有 RM 提交/回滾 資源减余,事務(wù)二階段結(jié)束综苔。

演示項(xiàng)目

Seata提供了很多Demo工程,這里選擇了springboot-dubbo-seata 項(xiàng)目位岔,基于 Spring Boot + Dubbo 的示例如筛。官方源碼:https://github.com/seata/seata-samples

此項(xiàng)目包含如下服務(wù):

  • samples-business 業(yè)務(wù)服務(wù)
  • samples-account 賬號(hào)服務(wù)
  • samples-order 訂單服務(wù)
  • samples-storage 庫(kù)存服務(wù)

他們之間的關(guān)系如下圖:

調(diào)用關(guān)系

數(shù)據(jù)準(zhǔn)備

使用Mysql創(chuàng)建seata數(shù)據(jù)庫(kù),執(zhí)行初始化腳本db_seata.sql抒抬。

/*
Navicat MySQL Data Transfer

Source Server         : account
Source Server Version : 50614
Source Host           : localhost:3306
Source Database       : db_gts_fescar

Target Server Type    : MYSQL
Target Server Version : 50614
File Encoding         : 65001

Date: 2019-01-26 10:23:10
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_account
-- ----------------------------
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;

-- ----------------------------
-- Records of t_account
-- ----------------------------
INSERT INTO `t_account` VALUES ('1', '1', '4000.00');

-- ----------------------------
-- Table structure for t_order
-- ----------------------------
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;

-- ----------------------------
-- Records of t_order
-- ----------------------------

-- ----------------------------
-- Table structure for t_storage
-- ----------------------------
DROP TABLE IF EXISTS `t_storage`;
CREATE TABLE `t_storage` (
  `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;

-- ----------------------------
-- Records of t_storage
-- ----------------------------
INSERT INTO `t_storage` VALUES ('1', 'C201901140001', '水杯', '1000');

-- ----------------------------
-- Table structure for undo_log
-- 注意此處0.3.0+ 增加唯一索引 ux_undo_log
-- ----------------------------
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,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of undo_log
-- ----------------------------
SET FOREIGN_KEY_CHECKS=1;

這里創(chuàng)建了4個(gè)表:t_account杨刨、t_order、t_storage擦剑、undo_log妖胀。
其中undo_log是記錄需要回滾的事務(wù)芥颈,其余是業(yè)務(wù)表。

啟動(dòng)服務(wù)注冊(cè)中心

這里用的是alibaba的Nacos赚抡,請(qǐng)使用1.1.0版本爬坑,防止因?yàn)閐ubbo,nacos因版本不匹配出現(xiàn)的心跳請(qǐng)求出錯(cuò)的情況涂臣。

v1.1.0地址:https://github.com/alibaba/nacos/releases/tag/1.1.0

下載解壓后在bin目錄下執(zhí)行startup.cmd即可啟動(dòng)盾计,端口為8848

通過(guò)瀏覽器可訪問(wèn)控制臺(tái):http://127.0.0.1:8848/nacos/index.html,默認(rèn)用戶名/密碼為nacos/nacos赁遗。

nacos控制臺(tái)

啟動(dòng)Seata Server

從官網(wǎng)下載:https://github.com/seata/seata/releases署辉。最新版本0.8.1

下載解壓后在斌目錄下執(zhí)行:

seata-server.bat -p 8091 -h 127.0.0.1 -m file

啟動(dòng)演示工程

分別啟動(dòng):samples-account、samples-order岩四、samples-storage哭尝、samples-business

啟動(dòng)前需要修改配置文件(application.properties),配置數(shù)據(jù)庫(kù)連接:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

==注意==

服務(wù)可能會(huì)啟動(dòng)失敗

2019-09-30 14:32:15.205 ERROR 7208 --- [Create-60221145] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, 
url: jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=Asia/Shanghai, 
errorCode 0, state 08001

這是因?yàn)槲冶镜氐臄?shù)據(jù)庫(kù)是Mysql8剖煌,系統(tǒng)使用的mysql數(shù)據(jù)庫(kù)驅(qū)動(dòng)mysql-connector-java版本號(hào)為5.1.31刚夺。將版本升級(jí)就可以了。

<!-- <mysql-connector.version>5.1.31</mysql-connector.version>  -->
<mysql-connector.version>8.0.11</mysql-connector.version>

啟動(dòng)后可通過(guò)nacos控制臺(tái)看到服務(wù)是否已準(zhǔn)備就緒:

nacos控制臺(tái)

執(zhí)行正常的請(qǐng)求

使用curl請(qǐng)求http://localhost:8104/business/dubbo/buy

請(qǐng)求數(shù)據(jù):

{
    "userId":"1",
    "commodityCode":"C201901140001",
    "name":"cup",
    "count":2,
    "amount":"100"
}

返回操作成功:

C:\Users\WBPC1108>curl  -X POST -H "Content-Type:application/json" -d "{\"userId\":\"1\",\"commodityCode\":\"C201901140001\",\"name\":\"cup\",\"count\":2,\"amount\":\"100\"}" "http://localhost:8104/business/dubbo/buy"
{"status":200,"message":"成功","data":null}

查看數(shù)據(jù)變化末捣。

請(qǐng)求前:

請(qǐng)求前數(shù)據(jù)

請(qǐng)求后:

請(qǐng)求后數(shù)據(jù)

測(cè)試回滾請(qǐng)求

修改samples-business工程里的BusinessServiceImpl類,主動(dòng)拋出異常:

if (!flag) {
  throw new RuntimeException("測(cè)試拋異常后创橄,分布式事務(wù)回滾箩做!");
}

請(qǐng)求返回錯(cuò)誤信息,數(shù)據(jù)沒(méi)變化:

C:\Users\WBPC1108>curl  -X POST -H "Content-Type:application/json" -d "{\"userId\":\"1\",\"commodityCode\":\"C201901140001\",\"name\":\"cup\",\"count\":2,\"amount\":\"100\"}" "http://localhost:8104/business/dubbo/buy"
{"timestamp":"2019-09-30T08:25:54.248+0000","status":500,"error":"Internal Server Error","message":"測(cè)試拋異常后妥畏,分布式事務(wù)回滾邦邦!","path":"/business/dubbo/buy"}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市醉蚁,隨后出現(xiàn)的幾起案子燃辖,更是在濱河造成了極大的恐慌,老刑警劉巖网棍,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件黔龟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡滥玷,警方通過(guò)查閱死者的電腦和手機(jī)氏身,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惑畴,“玉大人蛋欣,你說(shuō)我怎么就攤上這事∪绱” “怎么了陷虎?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵到踏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我尚猿,道長(zhǎng)窝稿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任谊路,我火速辦了婚禮讹躯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缠劝。我一直安慰自己潮梯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布惨恭。 她就那樣靜靜地躺著秉馏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脱羡。 梳的紋絲不亂的頭發(fā)上萝究,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音锉罐,去河邊找鬼帆竹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛脓规,可吹牛的內(nèi)容都是我干的栽连。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼侨舆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼秒紧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起挨下,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤熔恢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后臭笆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叙淌,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年愁铺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凿菩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帜讲,死狀恐怖衅谷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情似将,我是刑警寧澤获黔,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布蚀苛,位于F島的核電站,受9級(jí)特大地震影響玷氏,放射性物質(zhì)發(fā)生泄漏堵未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一盏触、第九天 我趴在偏房一處隱蔽的房頂上張望渗蟹。 院中可真熱鬧,春花似錦赞辩、人聲如沸雌芽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)世落。三九已至,卻和暖如春糟需,著一層夾襖步出監(jiān)牢的瞬間屉佳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工洲押, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留武花,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓杈帐,卻偏偏與公主長(zhǎng)得像髓堪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娘荡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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