一、分布式事務(wù)簡介
1.1 概念
事務(wù)ACID:
-
A(Atomic):原子性,構(gòu)成事務(wù)的所有操作,要么都執(zhí)行完成,要么全部不執(zhí)行,不可能出現(xiàn)部分成功部分失 敗的情況。
-
C(Consistency):一致性,在事務(wù)執(zhí)行前后,數(shù)據(jù)庫的一致性約束沒有被破壞。比如:張三向李四轉(zhuǎn)100元, 轉(zhuǎn)賬前和轉(zhuǎn)賬后的數(shù)據(jù)是正確狀態(tài)這叫一致性,如果出現(xiàn)張三轉(zhuǎn)出100元,李四賬戶沒有增加100元這就出現(xiàn)了數(shù) 據(jù)錯誤,就沒有達到一致性。
-
I(Isolation):隔離性,數(shù)據(jù)庫中的事務(wù)一般都是并發(fā)的,隔離性是指并發(fā)的兩個事務(wù)的執(zhí)行互不干擾,一個事 務(wù)不能看到其他事務(wù)運行過程的中間狀態(tài)。通過配置事務(wù)隔離級別可以避臟讀、重復(fù)讀等問題。
-
D(Durability):持久性,事務(wù)完成之后,該事務(wù)對數(shù)據(jù)的更改會被持久化到數(shù)據(jù)庫,且不會被回滾。
1.2 事務(wù)詳解
-
本地事務(wù):同一數(shù)據(jù)庫和服務(wù)器,稱為本地事務(wù) 在計算機系統(tǒng)中,更多的是通過關(guān)系型數(shù)據(jù)庫來控制事務(wù),這是利用數(shù)據(jù)庫本身的事務(wù)特性來實現(xiàn)的,因此叫數(shù)據(jù)庫事務(wù),由于應(yīng)用主要靠關(guān)系數(shù)據(jù)庫來控制事務(wù),而數(shù)據(jù)庫通常和應(yīng)用在同一個服務(wù)器,所以基于關(guān)系型數(shù)據(jù)庫的事務(wù)又被稱為本地事務(wù)。
-
分布式事務(wù): 分布式事務(wù)指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點之上,且屬于不同的應(yīng)用,分布式事務(wù)需要保證這些操作要么全部成功,要么全部失敗。本質(zhì)上來說,分布式事務(wù)就是為了保證不同數(shù)據(jù)庫的數(shù)據(jù)一致性。
-
舉例: 分布式系統(tǒng)會把一個應(yīng)用系統(tǒng)拆分為可獨立部署的多個服務(wù),因此需要服務(wù)與服務(wù)之間遠程協(xié)作才能完成事務(wù)操 作,這種分布式系統(tǒng)環(huán)境下由不同的服務(wù)之間通過網(wǎng)絡(luò)遠程協(xié)作完成事務(wù)稱之為分布式事務(wù),例如用戶注冊送積分事務(wù)、創(chuàng)建訂單減庫存事務(wù),銀行轉(zhuǎn)賬事務(wù)等都是分布式事務(wù)。
通過以上的圖中我們可以看出,其實只要涉及到操作多個數(shù)據(jù)源,就可能會產(chǎn)生事務(wù)問題,當然在實際開發(fā)中我們要盡量避免這種問題的出現(xiàn),當然如果避免不了,我們就需要進行解決,在我們的微服務(wù)系統(tǒng)架構(gòu)中,目前比較好,比較常用的解決方案就是Seata。
二、分布式理論
隨著互聯(lián)化的蔓延,各種項目都逐漸向分布式服務(wù)做轉(zhuǎn)換。如今微服務(wù)已經(jīng)普遍存在,本地事務(wù)已經(jīng)無法滿足分布式的要求,由此分布式事務(wù)問題誕生。 分布式事務(wù)被稱為世界性的難題,目前分布式事務(wù)存在兩大理論依據(jù):CAP定律 BASE理論。
2.1 CAP定律
這個定理的內(nèi)容是指的是在一個分布式系統(tǒng)中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯性),三者不可得兼。
- 一致性(C)
在分布式系統(tǒng)中的所有數(shù)據(jù)備份,在同一時刻是否同樣的值。(等同于所有節(jié)點訪問同一份最新的數(shù)據(jù)副本) - 可用性(A)
在集群中一部分節(jié)點故障后,集群整體是否還能響應(yīng)客戶端的讀寫請求。(對數(shù)據(jù)更新具備高可用性) - 分區(qū)容錯性(P)
以實際效果而言,分區(qū)相當于對通信的時限要求。系統(tǒng)如果不能在時限內(nèi)達成數(shù)據(jù)一致性,就意味著發(fā)生了分區(qū)的情況,必須就當前操作在C和A之間做出選擇
CAP是無法同時存在的,以下通過這個例子來說明
2.2 BASE理論
BASE是Basically Available(基本可用)、Soft state(軟狀態(tài))和 Eventually consistent(最終一致性)三個短語的縮寫。BASE理論是對CAP中一致性和可用性權(quán)衡的結(jié)果,其來源于對大規(guī)?;ヂ?lián)網(wǎng)系統(tǒng)分布式實踐的總結(jié), 是基于CAP定理逐步演化而來的。BASE理論的核心思想是:即使無法做到強一致性,但每個應(yīng)用都可以根據(jù)自身業(yè)務(wù)特點,采用適當?shù)姆绞絹硎瓜到y(tǒng)達到最終一致性
-
基本可用
基本可用是指分布式系統(tǒng)在出現(xiàn)不可預(yù)知故障的時候,允許損失部分可用性—-注意,這絕不等價于系統(tǒng)不可用。比如:
(1)響應(yīng)時間上的損失。正常情況下,一個在線搜索引擎需要在0.5秒之內(nèi)返回給用戶相應(yīng)的查詢結(jié)果,但由于出現(xiàn)故障,查詢結(jié)果的響應(yīng)時間增加了1~2秒
(2)系統(tǒng)功能上的損失:正常情況下,在一個電子商務(wù)網(wǎng)站上進行購物的時候,消費者幾乎能夠順利完成每一筆訂單,但是在一些節(jié)日大促購物高峰的時候,由于消費者的購物行為激增,為了保護購物系統(tǒng)的穩(wěn)定性,部分消費者可能會被引導到一個降級頁面
-
軟狀態(tài)
軟狀態(tài)指允許系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),并認為該中間狀態(tài)的存在不會影響系統(tǒng)的整體可用性,即允許系統(tǒng)在不同節(jié)點的數(shù)據(jù)副本之間進行數(shù)據(jù)同步的過程存在延時
-
最終一致性
最終一致性強調(diào)的是所有的數(shù)據(jù)副本,在經(jīng)過一段時間的同步之后,最終都能夠達到一個一致的狀態(tài)。因此,最終一致性的本質(zhì)是需要系統(tǒng)保證最終數(shù)據(jù)能夠達到一致,而不需要實時保證系統(tǒng)數(shù)據(jù)的強一致性。
2.2.1 基本可用
基本可用:**保證核心服務(wù)是可以使用的,至于其他的服務(wù)可以適當?shù)慕档晚憫?yīng)時間,甚至是服務(wù)降級
2.2.2 軟狀態(tài)
軟狀態(tài):存在中間狀態(tài),不影響整體系統(tǒng)使用,數(shù)據(jù)同步存在延時
2.2.3 最終一致性
最終一致性:再過了流量高峰期以后,經(jīng)過一段時間的同步,保持各服務(wù)數(shù)據(jù)的一致
三、分布式事務(wù)解決方案
3.1 什么是2PC
2PC即兩階段提交協(xié)議,是將整個事務(wù)流程分為兩個階段,P是指準備階段,C是指提交階段。
-
準備階段(Prepare phase)
-
提交階段(commit phase)
舉例:比如說相親對象兩個人去吃飯,店老板要求,先付錢在吃飯,這是男女雙方提出了AA,也就是說只有男女雙方都付錢,才能落座吃飯,但是只要兩個人中有一個不統(tǒng)一付款就不能落座吃飯。
-
準備階段:老板要求男方付款,男方付款。老板要求女方付款,女方付款
-
提交階段:老板出餐,兩人紛紛落座
其實此例子就形成了一個事務(wù),如果男女雙方有一個人拒絕付款,那么老板就不會出餐,并且會把已收取的錢原路退回。
真?zhèn)€事務(wù)過程是由事務(wù)管理器和參與者組成的,店老板就是事務(wù)管管理器,男女雙發(fā)就是參與者,事務(wù)管理器決策整個分布式事務(wù)在計算機中關(guān)系數(shù)據(jù)庫支持的兩階段提交協(xié)議:
-
準備階段(Prepare phase):事務(wù)管理器給每個參與者發(fā)送Prepare消息,每個數(shù)據(jù)庫參與者在本地執(zhí)行事務(wù),并寫本地的Undo/Redo日志,此時事務(wù)沒有提交。
-
(Undo日志是記錄修改前的數(shù)據(jù),用于數(shù)據(jù)庫回滾,Redo日志是記錄修改后的數(shù)據(jù),用于提交事務(wù)后寫入數(shù)據(jù)文件)
-
提交階段(commit phase):如果事務(wù)管理器收到了參與者的執(zhí)行失敗或者超時消息時,直接給每個參與者發(fā)送回滾(Rollback)消息;否則,發(fā)送提交(Commit)消息;參與者根據(jù)事務(wù)管理器的指令執(zhí)行提交或者回滾操作,并釋放事務(wù)處理過程中使用的資源。
四、Seata初始
官網(wǎng):https://seata.io/zh-cn/docs/overview/what-is-seata.html
概念:Seata 是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡單易用的分布式事務(wù)服務(wù)。Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。
在我們的微服務(wù)系統(tǒng)中,對應(yīng)業(yè)務(wù)被對應(yīng)的拆分成獨立模塊,在官方提供的架構(gòu)圖中,我們可以看出當前是三個服務(wù):
-
倉儲服務(wù):對給定的商品進行增刪操作記錄數(shù)量
-
訂單服務(wù):根據(jù)采購者的需求創(chuàng)建訂單
-
賬戶服務(wù):從用戶賬戶中扣除余額、積分等
在這套架構(gòu)中,用戶下單購買商品的業(yè)務(wù),就需要三個服務(wù)來完成,每個服務(wù)內(nèi)部的數(shù)據(jù)一致性由本地事務(wù)來保證,但是全局的數(shù)據(jù)一致性問題就沒辦法保證,Seata就是來進行解決這種問題的解決方案。
4.2 Seata核心概念
官網(wǎng)地址:https://seata.io/zh-cn/docs/overview/terminology.html
要了解Seata,首先我們要了解一下Seata的幾個關(guān)鍵的概念:
-
TC (Transaction Coordinator) - 事務(wù)協(xié)調(diào)者
維護全局和分支事務(wù)的狀態(tài),驅(qū)動全局事務(wù)提交或回滾。
-
TM (Transaction Manager) - 事務(wù)管理器(發(fā)起者,同時也是RM的一種)
定義全局事務(wù)的范圍:開始全局事務(wù)、提交或回滾全局事務(wù)。
-
RM (Resource Manager) - 資源管理器(每個參與事務(wù)的微服務(wù))
管理分支事務(wù)處理的資源,與TC交談以注冊分支事務(wù)和報告分支事務(wù)的狀態(tài),并驅(qū)動分支事務(wù)提交或回滾。
五、Seata下載配置
官方下載地址:https://github.com/seata/seata/releases
下載之后解壓
我下載的版本為1.8.0
5.1 Seata-Server配置文件
修改seata-server-1.8.0\seata\conf下面的application.yml文件
主要配置如下,seata下面的config、registry、store
注冊中心、配置中心、模式
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
# extend:
# logstash-appender:
# destination: 127.0.0.1:4560
# kafka-appender:
# bootstrap-servers: 127.0.0.1:9092
# topic: logback_to_logstash
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
serverAddr: 127.0.0.1:8848
namespace:
group: SEATA_GROUP
username: nacos
password: nacos
dataId: seataServer.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace:
cluster: default
username: nacos
password: nacos
store:
# support: file 、 db 、 redis
mode: db
session:
mode: db
lock:
mode: db
db:
datasource: durid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://rm-8vb0l231l029347gjco.mysql.zhangbei.rds.aliyuncs.com:3306/pro-2022?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
user: root
password: wsrbb
min-conn: 10
max-conn: 100
global-table: global-table
branch-table: branch-table
lock-table: lock-table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
5.2 Seata-server db創(chuàng)建
在seata-server-1.8.0\seata\script\server\db 下找到數(shù)據(jù)庫SQL腳本,根據(jù)自己數(shù)據(jù)庫類型選擇對應(yīng)的腳本執(zhí)行即可
數(shù)據(jù)庫名稱隨意,只要能找到就行。執(zhí)行完成后如下
5.3 Nacos添加配置文件config.txt
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
#Used for password encryption
store.publicKey=
#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
store.db.user=root
store.db.password=wsrbb
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.sentinel.sentinelPassword=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
配置文件的注意事項:
service.vgroupMapping.my_tx_group=default
數(shù)據(jù)庫修改上面配置的位置
有可能提示腳本有誤。只需要吧一些空值給刪除即可
5.4 啟動Seata
啟動Seata腳本。我這里是window版本,所以直接執(zhí)行seata-server.bat
注意: 確保Nacos服務(wù)啟動成功,Seata也是一個服務(wù),需要注冊到Nacos中
六、AT模式
AT模式是一種無侵入的分布式事務(wù)解決方案,在 AT 模式下,用戶只需關(guān)注自己的“業(yè)務(wù) SQL”,用戶的 “業(yè)務(wù) SQL” 作為一階段,Seata 框架會自動生成事務(wù)的二階段提交和回滾操作。
6.1 整體概覽
兩階段提交協(xié)議的演變:
- 一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個本地事務(wù)中提交,釋放本地鎖和連接資源。
- 二階段:
- 提交異步化,非??焖俚赝瓿?。
- 回滾通過一階段的回滾日志進行反向補償。
一階段
在一階段中,Seata會攔截“業(yè)務(wù)SQL“,首先解析SQL語義,找到要更新的業(yè)務(wù)數(shù)據(jù),在數(shù)據(jù)被更新前,保存下來"undo",然后執(zhí)行”業(yè)務(wù)SQL“更新數(shù)據(jù),更新之后再次保存數(shù)據(jù)”redo“,最后生成行鎖,這些操作都在本地數(shù)據(jù)庫事務(wù)內(nèi)完成,這樣保證了一階段的原子性。
二階段
相對一階段,二階段比較簡單,負責整體的回滾和提交,如果之前的一階段中有本地事務(wù)沒有通過,那么就執(zhí)行全局回滾,否在執(zhí)行全局提交,回滾用到的就是一階段記錄的"undo Log",通過回滾記錄生成反向更新SQL并執(zhí)行,以完成分支的回滾。當然事務(wù)完成后會釋放所有資源和刪除所有日志。
6.2 案例講解
- 創(chuàng)建兩個服務(wù)order,stock
- order服務(wù)通過openfegin遠程調(diào)用stock,執(zhí)行業(yè)務(wù)邏輯操作
6.2.1 創(chuàng)建兩個數(shù)據(jù)庫order、stock
執(zhí)行undo_logo日志回滾表
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;
6.2.2 對應(yīng)服務(wù)增加依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
6.2.3 配置yml文件
注意:兩個服務(wù)的配置文件保持一致
server:
port: 8801
spring:
application:
name: seata-order
cloud:
nacos:
discovery:
server-addr: localhost:8848
alibaba:
seata:
tx-service-group: mygroup # 事務(wù)組, 隨便寫
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/order?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root
password: wsrbb
type: com.alibaba.druid.pool.DruidDataSource
management:
endpoint:
web:
exposure:
include: '*'
seata:
tx-service-group: mygroup # 事務(wù)組名稱,要和服務(wù)端對應(yīng)
service:
vgroup-mapping:
mygroup: default # key是事務(wù)組名稱 value要和服務(wù)端的機房名稱保持一致
6.2.4 關(guān)鍵代碼
加上全部事務(wù)@GlobalTransactional
@Resource
private JdbcTemplate jdbcTemplate;
@Autowired
private StockApi stockApi;
@GlobalTransactional
public void create(){
stockApi.decrement();
int i = 1/0;
jdbcTemplate.update("insert into order_at (product_id, count) values (1, 10)");
System.out.println("生成訂單");
}
6.2.5 啟動order、stock服務(wù)
瀏覽器訪問http://localhost:8801/order/order/create,此時服務(wù)肯定會拋出異常,數(shù)據(jù)應(yīng)該回滾。
我們通過debug模式可以看到減庫存stock服務(wù)在數(shù)據(jù)庫中已經(jīng)減掉了。此時發(fā)生異常后數(shù)據(jù)回滾
undo_log表快照記錄文章來源:http://www.zghlxwxcb.cn/news/detail-820475.html
如果對你有幫助,可以關(guān)注博主(不定期更新各種技術(shù)文檔) 給博主一個免費的點贊以示鼓勵,謝謝 ! 歡迎各位??點贊??評論收藏??文章來源地址http://www.zghlxwxcb.cn/news/detail-820475.html
到了這里,關(guān)于08-微服務(wù)Seata分布式事務(wù)使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!