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