javascript
springboot整合oracle_SpringBoot2.x系列教程67--Spring Boot整合分布式事务简介
SpringBoot2.x系列教程67--Spring Boot整合分布式事務(wù)簡(jiǎn)介
作者:一一哥
一. 分布式事務(wù)簡(jiǎn)介
1. 什么是分布式事務(wù)
百度百科對(duì)分布式事務(wù)的解釋如下:
分布式事務(wù)就是指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于分布式系統(tǒng)的不同節(jié)點(diǎn)之上。當(dāng)數(shù)據(jù)庫(kù)的數(shù)據(jù)越來越大,數(shù)據(jù)庫(kù)無法承受起壓力,就會(huì)開始分庫(kù)分表,分庫(kù)分表后不同的庫(kù)就會(huì)分布在不同的服務(wù)器上,明顯的就會(huì)出現(xiàn)數(shù)據(jù)一致性問題。或者同一個(gè)事務(wù)中要調(diào)用的不同系統(tǒng)的不同的庫(kù),也要保證要不全都成功,要不全部回滾。簡(jiǎn)單的說,就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用。分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。本質(zhì)上來說,分布式事務(wù)就是為了保證不同數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性。
2. 分布式事務(wù)產(chǎn)生的原因
2.1 數(shù)據(jù)庫(kù)分庫(kù)分表
當(dāng)數(shù)據(jù)庫(kù)單表一年產(chǎn)生的數(shù)據(jù)超過1000W,那么就可能要考慮分庫(kù)分表,也就是說要把原來的一個(gè)數(shù)據(jù)庫(kù)變成多個(gè)數(shù)據(jù)庫(kù)。這時(shí)候,如果一個(gè)操作既要訪問01庫(kù),又訪問02庫(kù),而且還要保證數(shù)據(jù)的一致性,那么就要用到分布式事務(wù)。2.2 應(yīng)用SOA化
所謂的SOA,就是業(yè)務(wù)的服務(wù)化。比如原來單機(jī)支撐了整個(gè)電商網(wǎng)站,現(xiàn)在對(duì)整個(gè)網(wǎng)站進(jìn)行拆解,分離出了訂單中心、庫(kù)存中心。對(duì)于訂單中心,有專門的數(shù)據(jù)庫(kù)存儲(chǔ)訂單信息,庫(kù)存中心也會(huì)有專門的數(shù)據(jù)庫(kù)存儲(chǔ)庫(kù)存信息。這時(shí)候如果要同時(shí)對(duì)訂單和庫(kù)存進(jìn)行操作,那么就會(huì)涉及到訂單數(shù)據(jù)庫(kù)和庫(kù)存數(shù)據(jù)庫(kù),為了保證數(shù)據(jù)一致性,就需要用到分布式事務(wù)。
以上兩種情況表象不同,但是本質(zhì)相同,都是因?yàn)橐僮鞯臄?shù)據(jù)庫(kù)變多了!
3. 分布式事務(wù)的應(yīng)用場(chǎng)景
3.1 支付
我們?cè)谶M(jìn)行支付的時(shí)候,會(huì)對(duì)買家賬戶進(jìn)行扣款,同時(shí)對(duì)賣家賬戶進(jìn)行加錢。這些操作必須在一個(gè)事務(wù)里執(zhí)行,要么全部成功,要么全部失敗。而對(duì)于買家賬戶屬于買家中心,對(duì)應(yīng)的是買家數(shù)據(jù)庫(kù),而賣家賬戶屬于賣家中心,對(duì)應(yīng)的是賣家數(shù)據(jù)庫(kù),對(duì)不同數(shù)據(jù)庫(kù)的操作必然需要引入分布式事務(wù)。
3.2 在線下單
買家在電商平臺(tái)下單,往往會(huì)涉及到兩個(gè)動(dòng)作,一個(gè)是扣庫(kù)存,第二個(gè)是更新訂單狀態(tài),庫(kù)存和訂單一般屬于不同的數(shù)據(jù)庫(kù),需要使用分布式事務(wù)保證數(shù)據(jù)一致性。
二. XA 事務(wù)
1. XA協(xié)議
XA(eXtended Architecture)是指由X/Open 組織提出的分布式交易處理的規(guī)范。XA 是一個(gè)分布式事務(wù)協(xié)議,由Tuxedo 提出,所以分布式事務(wù)也稱為XA 事務(wù)。2. XA協(xié)議構(gòu)成
XA 協(xié)議主要定義了事務(wù)管理器TM(Transaction Manager,協(xié)調(diào)者)和資源管理器RM(Resource Manager,參與者)之間的接口。其中,資源管理器往往由數(shù)據(jù)庫(kù)實(shí)現(xiàn),如Oracle、DB2、MySQL,這些商業(yè)數(shù)據(jù)庫(kù)都實(shí)現(xiàn)了XA 接口,而事務(wù)管理器作為全局的調(diào)度者,負(fù)責(zé)各個(gè)本地資源的提交和回滾。XA 事務(wù)是基于兩階段提交(Two-phaseCommit,2PC)協(xié)議實(shí)現(xiàn)的,可以保證數(shù)據(jù)的強(qiáng)一致性,許多分布式關(guān)系型數(shù)據(jù)管理系統(tǒng)都采用此協(xié)議來完成分布式。階段一為準(zhǔn)備階段,即所有的參與者準(zhǔn)備執(zhí)行事務(wù)并鎖住需要的資源。當(dāng)參與者Ready時(shí),向TM 匯報(bào)自己已經(jīng)準(zhǔn)備好。階段二為提交階段。當(dāng)TM 確認(rèn)所有參與者都Ready 后,向所有參與者發(fā)送COMMIT 命令。XA 事務(wù)允許不同數(shù)據(jù)庫(kù)的分布式事務(wù),Oracle、MySQL 和SQL Server 都支持XA 事務(wù)。
3. XA事務(wù)構(gòu)成
XA事務(wù)由一個(gè)或多個(gè)資源管理器(RM)、一個(gè)事務(wù)管理器(TM)和一個(gè)應(yīng)用程序(ApplicationProgram)組成。
- 資源管理器: 提供訪問事務(wù)資源的方法,通常一個(gè)數(shù)據(jù)庫(kù)就是一個(gè)資源管理器。
- 事務(wù)管理器: 協(xié)調(diào)參與全局事務(wù)中的各個(gè)事務(wù),需要和參與全局事務(wù)的所有資源管理器進(jìn)行通信。
- 應(yīng)用程序: 定義事務(wù)的邊界。
4. XA事務(wù)注意事項(xiàng)
XA 事務(wù)的缺點(diǎn)是性能不好,且無法滿足高并發(fā)場(chǎng)景。一個(gè)數(shù)據(jù)庫(kù)的事務(wù)和多個(gè)數(shù)據(jù)庫(kù)間的XA 事務(wù)性能會(huì)相差很多。因此,要盡量避免XA 事務(wù),如可以將數(shù)據(jù)寫入本地,用高性能的消息系統(tǒng)分發(fā)數(shù)據(jù),或使用數(shù)據(jù)庫(kù)復(fù)制等技術(shù)。只有在其他辦法都無法實(shí)現(xiàn)業(yè)務(wù)需求,且性能不是瓶頸時(shí)才使用XA。三. 常見的分布式事務(wù)解決方案
1. 基于XA協(xié)議的兩階段提交(2PC)
XA是一個(gè)分布式事務(wù)協(xié)議,由Tuxedo提出。XA中大致分為兩部分:事務(wù)管理器和本地資源管理器。其中本地資源管理器往往由數(shù)據(jù)庫(kù)實(shí)現(xiàn),比如Oracle、MySQL這些商業(yè)數(shù)據(jù)庫(kù)都實(shí)現(xiàn)了XA接口,而事務(wù)管理器作為全局的調(diào)度者,負(fù)責(zé)各個(gè)本地資源的提交和回滾。XA實(shí)現(xiàn)分布式事務(wù)的原理如下:
總的來說,XA協(xié)議比較簡(jiǎn)單,而且一旦商業(yè)數(shù)據(jù)庫(kù)實(shí)現(xiàn)了XA協(xié)議,使用分布式事務(wù)的成本也比較低。
但是,XA也有致命的缺點(diǎn),那就是性能不理想,特別是在交易下單鏈路,往往并發(fā)量很高,XA無法滿足高并發(fā)場(chǎng)景。XA目前在商業(yè)數(shù)據(jù)庫(kù)支持的比較理想,在MySQL數(shù)據(jù)庫(kù)中支持的不太理想,MySQL的XA實(shí)現(xiàn),沒有記錄prepare階段日志,主備切換會(huì)導(dǎo)致主庫(kù)與備庫(kù)數(shù)據(jù)不一致。許多NoSQL也沒有支持XA,這讓XA的應(yīng)用場(chǎng)景變得非常狹隘。XA兩階段提交的不足
- 1.性能問題
XA協(xié)議遵循強(qiáng)一致性。在事務(wù)執(zhí)行過程中,各個(gè)節(jié)點(diǎn)占用著數(shù)據(jù)庫(kù)資源,只有當(dāng)所有節(jié)點(diǎn)準(zhǔn)備完畢,事務(wù)協(xié)調(diào)者才會(huì)通知提交,參與者提交后釋放資源。這樣的過程有著非常明顯的性能問題。 - 2.協(xié)調(diào)者單點(diǎn)故障問題
事務(wù)協(xié)調(diào)者是整個(gè)XA模型的核心,一旦事務(wù)協(xié)調(diào)者節(jié)點(diǎn)掛掉,參與者收不到提交或是回滾通知,參與者會(huì)一直處于中間狀態(tài)無法完成事務(wù)。 - 3.丟失消息導(dǎo)致的不一致問題
在XA協(xié)議的第二個(gè)階段,如果發(fā)生局部網(wǎng)絡(luò)問題,一部分事務(wù)參與者收到了提交消息,另一部分事務(wù)參與者沒收到提交消息,那么就導(dǎo)致了節(jié)點(diǎn)之間數(shù)據(jù)的不一致。
總結(jié):
- 優(yōu)點(diǎn): 盡量保證了數(shù)據(jù)的強(qiáng)一致,適合對(duì)數(shù)據(jù)強(qiáng)一致要求很高的關(guān)鍵領(lǐng)域(其實(shí)也不能100%保證強(qiáng)一致)
- 缺點(diǎn): 實(shí)現(xiàn)復(fù)雜,犧牲了可用性,對(duì)性能影響較大,不適合高并發(fā)高性能場(chǎng)景,如果分布式系統(tǒng)跨接口調(diào)用。
2. 消息事務(wù)+最終一致性
所謂的消息事務(wù)就是基于消息中間件的兩階段提交,本質(zhì)上是對(duì)消息中間件的一種特殊利用,它是將本地事務(wù)和發(fā)消息放在了一個(gè)分布式事務(wù)里,保證要么本地操作成功成功并且對(duì)外發(fā)消息成功,要么兩者都失敗,開源的RocketMQ就支持這一特性。業(yè)務(wù)示意圖:
具體原理如下:
- 1. A系統(tǒng)向消息中間件發(fā)送一條預(yù)備消息;
- 2. 消息中間件保存預(yù)備消息并返回成功;
- 3. A執(zhí)行本地事務(wù);
- 4. A發(fā)送提交消息給消息中間件。
通過以上4步完成了一個(gè)消息事務(wù)。對(duì)于以上的4個(gè)步驟,每個(gè)步驟都可能產(chǎn)生錯(cuò)誤,下面一一分析:
1.如果步驟一出錯(cuò),則整個(gè)事務(wù)失敗,不會(huì)執(zhí)行A的本地操作;2.如果步驟二出錯(cuò),則整個(gè)事務(wù)失敗,不會(huì)執(zhí)行A的本地操作;3.如果步驟三出錯(cuò),這時(shí)候需要回滾預(yù)備消息,怎么回滾呢?答案是A系統(tǒng)實(shí)現(xiàn)一個(gè)消息中間件的回調(diào)接口,消息中間件會(huì)不斷的執(zhí)行回調(diào)接口,檢查A事務(wù)執(zhí)行是否執(zhí)行成功,如果失敗則回滾預(yù)備消息。4.如果步驟四出錯(cuò),這時(shí)候A的本地事務(wù)是成功的,那么消息中間件要回滾A嗎?答案是不需要,其實(shí)通過回調(diào)接口,消息中間件能夠檢查到A執(zhí)行成功了,這時(shí)候其實(shí)不需要A發(fā)提交消息了,消息中間件可以自己對(duì)消息進(jìn)行提交,從而完成整個(gè)消息事務(wù)。消息事務(wù)小結(jié):
- 優(yōu)點(diǎn):實(shí)現(xiàn)了最終一致性,不需要依賴本地?cái)?shù)據(jù)庫(kù)事務(wù)。
- 缺點(diǎn):實(shí)現(xiàn)難度大,主流MQ不支持,RocketMQ事務(wù)消息部分代碼也未開源。
3. 本地消息表(異步確保)
基于消息中間件的兩階段提交往往用在高并發(fā)場(chǎng)景下,將一個(gè)分布式事務(wù)拆成一個(gè)消息事務(wù)(A系統(tǒng)的本地操作+發(fā)消息)和B系統(tǒng)的本地操作。其中B系統(tǒng)的操作由消息驅(qū)動(dòng),只要消息事務(wù)成功,那么A操作一定成功,消息也一定發(fā)出來了。這時(shí)候B會(huì)收到消息去執(zhí)行本地操作,如果本地操作失敗,消息會(huì)重投,直到B操作成功,這樣就變相地實(shí)現(xiàn)了A與B的分布式事務(wù)。原理如下:
雖然上面的方案能夠完成A和B的操作,但是A和B并不是嚴(yán)格一致的,而是最終一致的。我們?cè)谶@里犧牲了一致性,換來了性能的大幅度提升。當(dāng)然,這種玩法也是有風(fēng)險(xiǎn)的,如果B一直執(zhí)行不成功,那么一致性會(huì)被破壞,具體要不要玩,還是得看業(yè)務(wù)能夠承擔(dān)多少風(fēng)險(xiǎn)。
4. 補(bǔ)償事務(wù)的TCC編程模式
所謂的補(bǔ)償事務(wù)的TCC編程模式,也是兩階段提交的一個(gè)變種。TCC提供了一個(gè)編程框架,將整個(gè)業(yè)務(wù)邏輯分為三塊:Try、Confirm和Cancel三個(gè)操作。以在線下單為例,Try階段會(huì)去扣庫(kù)存,Confirm階段則是去更新訂單狀態(tài),如果更新訂單失敗,則進(jìn)入Cancel階段,會(huì)去恢復(fù)庫(kù)存。總之,TCC就是通過代碼人為實(shí)現(xiàn)了兩階段提交,不同的業(yè)務(wù)場(chǎng)景所寫的代碼都不一樣,復(fù)雜度也不一樣,因此,這種模式并不能很好地被復(fù)用。
四. 總結(jié)
分布式事務(wù),本質(zhì)上是對(duì)多個(gè)數(shù)據(jù)庫(kù)的事務(wù)進(jìn)行統(tǒng)一控制,按照控制力度可以分為:不控制、部分控制和完全控制。- 不控制就是不引入分布式事務(wù)。
- 部分控制就是各種變種的兩階段提交,包括上面提到的消息事務(wù)+最終一致性、TCC模式,而完全控制就是完全實(shí)現(xiàn)兩階段提交。部分控制的好處是并發(fā)量和性能很好,缺點(diǎn)是數(shù)據(jù)一致性減弱了。
- 完全控制則是犧牲了性能,保障了一致性,具體用哪種方式,最終還是取決于業(yè)務(wù)場(chǎng)景。
作為技術(shù)人員,一定不能忘了技術(shù)是為業(yè)務(wù)服務(wù)的,不要為了技術(shù)而技術(shù),針對(duì)不同業(yè)務(wù)進(jìn)行技術(shù)選型也是一種很重要的能力!
總結(jié)
以上是生活随笔為你收集整理的springboot整合oracle_SpringBoot2.x系列教程67--Spring Boot整合分布式事务简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 回溯法 01背包问题_Py
- 下一篇: 如何得到iterator的当前元素_链表