- 1. 什么是全局事務(wù)呢?
- 2. 2pc提交協(xié)議
- 3. XA事務(wù)存在的問題
- 4. CAP理論
- 5. Sharding-JDBC分布式事務(wù)支持
- 6. 項目地址
在我們使用Sharding JDBC分庫分表的時候,會帶來另外一個問題,就是分布式事務(wù)問題,如下圖所示。用戶采購商品業(yè)務(wù),整個業(yè)務(wù)包含3個微服務(wù):
- 庫存服務(wù): 扣減給定商品的庫存數(shù)量。
- 訂單服務(wù): 根據(jù)采購請求生成訂單。
- 賬戶服務(wù): 用戶賬戶金額扣減。
這三個業(yè)務(wù)操作應(yīng)該屬于同一個事務(wù),但是這些數(shù)據(jù)卻分配在不同的數(shù)據(jù)庫上,所以沒辦法采用數(shù)據(jù)庫的事務(wù)來保證數(shù)據(jù)一致性。
這個時候,要解決分布式事務(wù)問題,就需要引入全局事務(wù)。
1. 什么是全局事務(wù)呢?
全局事務(wù)是一個DTP模型的事務(wù),所謂DTP模型指的是 X/Open DTP (X/Open Distributed Transaction Processing Reference Model
),是 X/Open 這個組織定義的一套分布式事務(wù)的標(biāo)準(zhǔn)。
X/Open,即現(xiàn)在的open group,是一個獨立的組織,主要負責(zé)制定各種行業(yè)技術(shù)標(biāo)準(zhǔn)。
官網(wǎng)地址:http://www.opengroup.org/
X/Open組織主要由各大知名公司或者廠商進行支持,這些組織不光遵循X/Open組織定義的行業(yè)技術(shù)標(biāo)準(zhǔn),也參與到標(biāo)準(zhǔn)的制定。
X/Open了定義了規(guī)范和API接口,由這個廠商進行具體的實現(xiàn),這個標(biāo)準(zhǔn)提出了使用二階段提交(2PC –Two-Phase-Commit
)來保證分布式事務(wù)的完整性。后來J2EE也遵循了X/OpenDTP規(guī)范,設(shè)計并實現(xiàn)了java里的分布式事務(wù)編程接口規(guī)范-JTA,如下圖所示,表示一個X/Open DTP模型。
X/Open DTP模型定義了三個角色和兩個協(xié)議,其中三個角色分別如下:
- AP(Application Program) ,表示應(yīng)用程序,也可以理解成使用DTP模型的程序
- RM(Resource Manager) ,資源管理器,這個資源可以是數(shù)據(jù)庫, 應(yīng)用程序通過資源管理器對資源進行控制,資源管理器必須實現(xiàn)XA定義的接口
- TM(Transaction Manager) ,表示事務(wù)管理器,負責(zé)協(xié)調(diào)和管理全局事務(wù),事務(wù)管理器控制整個全局事務(wù),管理事務(wù)的生命周期,并且協(xié)調(diào)資源。
兩個協(xié)議分別是:
XA協(xié)議: XA 是X/Open DTP定義的資源管理器和事務(wù)管理器之間的接口規(guī)范,TM用它來通知和協(xié)調(diào)相關(guān)RM事務(wù)的開始、結(jié)束、提交或回滾。
目前Oracle、Mysql、DB2都提供了對XA的支持;XA接口是雙向的系統(tǒng)接口,在事務(wù)管理器(TM ) 以及多個資源管理器之間形成通信的橋梁(XA不能自動 提交)
- https://dev.mysql.com/doc/refman/8.0/en/xa.html
- https://dev.mysql.com/doc/refman/8.0/en/xa-statements.html
XA協(xié)議的語法,主流的數(shù)據(jù)庫都支持 XA協(xié)議,從而能夠?qū)崿F(xiàn)跨數(shù)據(jù)庫事務(wù)。
XA{START|BEGIN}xid[JOIN|RESUME]--負責(zé)開啟或者恢復(fù)一個事務(wù)分支,并且管理XID到調(diào)用線程
XAENDxid[SUSPEND[FORMIGRATE]]--負責(zé)取消當(dāng)前線程與事務(wù)分支的關(guān)聯(lián)
XAPREPARExid--負責(zé)詢問RM是否準(zhǔn)備好了提交事務(wù)分支
XACOMMITxid[ONEPHASE]--知RM提交事務(wù)分支
XAROLLBACKxid--通知RM回滾事務(wù)分支
XARECOVER[CONVERTXID]
TX協(xié)議: 全局事務(wù)管理器與資源管理器之間通信的接口
在分布式系統(tǒng)中,每一個機器節(jié)點雖然都能夠明確知道自己在進行事務(wù)操作過程中的結(jié)果是成功還是失敗,但卻無法直接獲取到其他分布式節(jié)點的操作結(jié)果。
因此當(dāng)一個事務(wù)操作需要跨越多個分布式節(jié)點的時候,為了保持事務(wù)處理的ACID特性,就需要引入一個“協(xié)調(diào)者”(TM)來統(tǒng)一調(diào)度所有分布式節(jié)點的執(zhí)行邏輯,這些被調(diào)度的分布式節(jié)點被稱為AP。TM負責(zé)調(diào)度AP的行為,并最終決定這些AP是否要把事務(wù)真正進行提交到(RM)。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
2. 2pc提交協(xié)議
在X/OpenDTP模型中,一個分布式事務(wù)所涉及的SQL邏輯都執(zhí)行完成,并到了(RM)要最后提交事務(wù)的關(guān)鍵時刻,為了避免分布式系統(tǒng)所固有的不可靠性導(dǎo)致提交事務(wù)意外失敗,TM 果斷決定實施兩步走的方案,這個就稱為二階提交,如下圖所示。
二階段提交,是計算機網(wǎng)絡(luò)尤其是在數(shù)據(jù)庫領(lǐng)域內(nèi),為了使基于分布式系統(tǒng)架構(gòu)下的所有節(jié)點在進行事務(wù)處理過程中能夠保持原子性和一致性而設(shè)計的一種算法。通常,二階段提交協(xié)議也被認為是一種一致性協(xié)議,用來保證分布式系統(tǒng)數(shù)據(jù)的一致性。
目前,絕大部分的關(guān)系型數(shù)據(jù)庫都是采用二階段提交協(xié)議來完成分布式事務(wù)處理的,利用該協(xié)議能夠非常方便地完成所有分布式事務(wù)AP的協(xié)調(diào),統(tǒng)一決定事務(wù)的提交或回滾,從而能夠有效保證分布式數(shù)據(jù)一致性,因此2pc也被廣泛運用在許多分布式系統(tǒng)中。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
3. XA事務(wù)存在的問題
上述基于XA協(xié)議的全局事務(wù),是屬于強一致性事務(wù),因為在全局事務(wù)中,只要有任何一個RM出現(xiàn)異常,都會導(dǎo)致全局事務(wù)回滾。同時,本地事務(wù)在Prepare階段鎖定資源時,如果有其他事務(wù)要要修改相同的數(shù)據(jù),就必須要等待前面的事務(wù)完成,這本身是無可厚非的設(shè)計,但是由于多個RM節(jié)點是跨網(wǎng)絡(luò),一旦出現(xiàn)網(wǎng)絡(luò)延遲,就導(dǎo)致該事務(wù)一直占用資源使得整體性能下降。
另外,在XA COMMIT階段,如果其中一個RM因為網(wǎng)絡(luò)超時沒有收到數(shù)據(jù)提交的指令,會導(dǎo)致數(shù)據(jù)不一致,為了解決這個問題,很多開源分布式事務(wù)框架都會提供重試機制來保證數(shù)據(jù)一致性。
4. CAP理論
說到強一致性的問題,必然要提到CAP理論。
CAP的含義:
- C:Consistency 一致性 同一數(shù)據(jù)的多個副本是否實時相同。
- A:Availability 可用性 可用性:一定時間內(nèi) & 系統(tǒng)返回一個明確的結(jié)果 則稱為該系統(tǒng)可用。
- P:Partition tolerance 分區(qū)容錯性 將同一服務(wù)分布在多個系統(tǒng)中,從而保證某一個系統(tǒng)宕機,仍然有其他系統(tǒng)提供相同的服務(wù)。
CAP理論告訴我們,在分布式系統(tǒng)中,C、A、P三個條件中我們最多只能選擇兩個。那么問題來了,究竟選擇哪兩個條件較為合適呢?
對于一個業(yè)務(wù)系統(tǒng)來說,分區(qū)容錯性是必須要滿足的條件。業(yè)務(wù)系統(tǒng)之所以使用分布式系統(tǒng),主要原因有兩個:
- 提升整體性能 當(dāng)業(yè)務(wù)量猛增,單個服務(wù)器已經(jīng)無法滿足我們的業(yè)務(wù)需求的時候,就需要使用分布式系統(tǒng),使用多個節(jié)點提供相同的功能,從而整體上提升系統(tǒng)的性能,這就是使用分布式系統(tǒng)的第一個原因。
- 實現(xiàn)分區(qū)容錯性 單一節(jié)點 或 多個節(jié)點處于相同的網(wǎng)絡(luò)環(huán)境下,那么會存在一定的風(fēng)險,萬一該機房斷電、該地區(qū)發(fā)生自然災(zāi)害,那么業(yè)務(wù)系統(tǒng)就全面癱瘓了。為了防止這一問題,采用分布式系統(tǒng),將多個子系統(tǒng)分布在不同的地域、不同的機房中,從而保證系統(tǒng)高可用性。
所以我們需要根據(jù)自己的業(yè)務(wù)需求,選擇采取CP還是AP。
5. Sharding-JDBC分布式事務(wù)支持
了解了X/Open DTP模型的全局事務(wù)解決方案,就必然需要一個成熟的技術(shù)中間件來簡化我們對于分布式事務(wù)的開發(fā)邏輯,而Sharding-JDBC提供了分布式事務(wù)解決方案。
Sharding-JDBC支持以下四種事務(wù)模型,實際上這些分布式事務(wù)模式都是集成開源的事務(wù)組件做的集成。
- Atomikos事務(wù)
- Narayana事務(wù)
- Bitronix事務(wù)
- Seata事務(wù)
Apache ShardingSphere 默認的 XA 事務(wù)管理器為 Atomikos,下面我們通過Atomikos來配置一個分布式事務(wù)的使用模型。
5.1 Atomikos事務(wù)
Atomikos是為Java平臺提供的開源的事務(wù)管理工具,它包含收費和開源兩個版本,開源版本基本能滿足我們的需求。
Atomikos實現(xiàn)了JTA/XA規(guī)范中的事務(wù)管理器(Transaction Manager
)應(yīng)該實現(xiàn)的相關(guān)接口。
JTA,即Java Transaction API
,JTA允許應(yīng)用程序執(zhí)行分布式事務(wù)處理——在兩個或多個網(wǎng)絡(luò)計算機資源上訪問并且更新數(shù)據(jù),JDBC驅(qū)動程序的JTA支持極大地增強了數(shù)據(jù)訪問能力。
-
TransactionManager : 常用方法,可以開啟、回滾、獲取事務(wù)。
begin(),rollback()…
-
XAResouce : 資源管理,通過Session來進行事務(wù)管理。
commit(xid)…
- XID : 每一個事務(wù)都分配一個特定的XID
JTA是如何實現(xiàn)多數(shù)據(jù)源的事務(wù)管理呢?
主要的原理是兩階段提交,以上面的請求業(yè)務(wù)為例,當(dāng)整個業(yè)務(wù)完成了之后只是第一階段提交,在第二階段提交之前會檢查其他所有事務(wù)是否已經(jīng)提交,如果前面出現(xiàn)了錯誤或是沒有提交,那么第二階段就不會提交,而是直接rollback操作,這樣所有的事務(wù)都會做Rollback操作。
5.2 實戰(zhàn)
5.2.1 項目搭建
使用IDEA直接創(chuàng)建Spring boot 項目即可。
5.2.2 依賴
由于使用XA事務(wù),所以除了Sharding依賴外還需要引入事務(wù)依賴。
<dependency>
<groupId>org.apache.shardingspheregroupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starterartifactId>
<version>5.0.0-alphaversion>
dependency>
<dependency>
<groupId>com.zaxxergroupId>
<artifactId>HikariCPartifactId>
<version>3.4.2version>
dependency>
<dependency>
<groupId>org.freemarkergroupId>
<artifactId>freemarkerartifactId>
dependency>
<dependency>
<groupId>org.apache.shardingspheregroupId>
<artifactId>shardingsphere-transaction-xa-coreartifactId>
<version>5.0.0-alphaversion>
dependency>
5.2.3 配置
接下來就是配置相關(guān)數(shù)據(jù)庫連接信息以及分片規(guī)則;
在這里主要做的是創(chuàng)建了兩個數(shù)據(jù)源(數(shù)據(jù)源最好設(shè)置兩臺服務(wù)器的數(shù)據(jù)庫)以及設(shè)置好了相應(yīng)的分庫規(guī)則。
server.port=8080
spring.mvc.view.prefix=classpath:/templates/
spring.mvc.view.suffix=.html
spring.shardingsphere.props.sql-show=true
spring.shardingsphere.datasource.names="ds-0,ds-1"
spring.shardingsphere.datasource.common.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.common.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc//localhost:3306/shard01?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-0.username=root
spring.shardingsphere.datasource.ds-0.password=123456
spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc//localhost:3306/shard02?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-1.username=root
spring.shardingsphere.datasource.ds-1.password=123456
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds-$->{user_id % 2}
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake
spring.shardingsphere.rules.sharding.key-generators.snowflake.type=SNOWFLAKE
spring.shardingsphere.rules.sharding.key-generators.snowflake.props.worker-id=123
5.2.4 事務(wù)一致性注解
Sharding jdbc解決事務(wù)一致性可以直接通過@ShardingTransactionType(TransactionType.XA)
注解實現(xiàn),我們只需要在對應(yīng)的方法上加上即可。
比如下圖,由于我們在配置文件中是通過user_id
進行分庫的,然后我們在這里通過隨機數(shù),會根據(jù)分片規(guī)則往兩個數(shù)據(jù)庫中插入數(shù)據(jù)。
當(dāng)i=4的時候,我們?nèi)藶榈闹圃飚惓#绻覀儾徊捎萌质聞?wù)的話,則之前插入的數(shù)據(jù)還會再數(shù)據(jù)庫中。所以這個時候我們只需要加上@ShardingTransactionType(TransactionType.XA)
注解即可,XA屬于強一致性。
6. 項目地址
https://gitee.com/cl1429745331/sharding-jdbc-demo
審核編輯 :李倩
-
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3822瀏覽量
64506 -
分布式
+關(guān)注
關(guān)注
1文章
908瀏覽量
74558 -
JDBC
+關(guān)注
關(guān)注
0文章
25瀏覽量
13413
原文標(biāo)題:Sharding JDBC 實戰(zhàn):分布式事務(wù)處理
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論