說了一些沒用的,腦子裏總想起這個事,不說不痛快,你們姑且就當笑話聽吧,下邊咱們進入正題程序員
引言
前兩天有個學弟公衆號留言,說讓講講分佈式事務,面試就掛在這個問題上。時下隨着微服務架構體系的流行,面試的題目也都慢慢開始升級,再也不是早些年單純的問點SSH框架知識、數據結構了。高併發
、高可用
、分佈式服務治理
、分佈式文件系統
、分佈式xxx
,反正和分佈式沾邊的都會問點, 項目實際用不用沒關係,關鍵你得了解,是否是總有一種學不動了的感受?面試
什麼是分佈式事務?
咱們看看百度上對於分佈式事務的定義:分佈式事務是指事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不一樣的分佈式系統的不一樣節點之上。sql
額~ 看了反而更懵逼了,簡單的畫個圖好讓你們理解一下,拿下單減庫存來講舉例:當系統的業務量很小時,「一站式
」的系統徹底能夠知足現有業務需求,全部的業務都共用一個數據庫,整個下單流程或許只用在一個方法裏同一個事務下操做數據庫便可。數據庫
此時全部操做都在一個事務裏,要麼所有提交,要麼所有回滾 。服務器
但隨着業務量不斷增加,「一站式
」系統漸漸扛不住巨大的流量,就須要對數據庫進行分庫分表,將業務服務化拆分(SOA
),就會分離出了訂單中心、用戶中心、庫存中心。而這樣就形成業務間相互隔離,每一個業務都維護着本身的數據庫,數據的交換隻能進行RPC調用。網絡
用戶再下單時,建立訂單和扣減庫存,須要同時對訂單DB和庫存DB進行操做。兩步操做必須同時成功,不然就會形成業務混亂,可此時咱們只能保證本身服務的數據一致性,沒法保證調用其餘服務的操做是否成功,因此爲了保證整個下單流程的數據一致性,就須要分佈式事務介入。數據結構
在說分佈式事務以前,先回憶一下事務的基本概念:事務是一個程序執行單元,裏面的全部操做要麼所有執行成功,要麼所有執行失敗。架構
一個事務有四個基本特性,也就是咱們常說的(ACID
)。併發
Atomicity
(原子性) :事務是一個不可分割的總體,事務內全部操做要麼全作成功,要麼全失敗。框架
Consistency
(一致性) :務執行先後,數據從一個狀態到另外一個狀態必須是一致的(A向B轉帳,不能出現A扣了錢,B卻沒收到)。
Isolation
(隔離性): 多個併發事務之間相互隔離,不能互相干擾。
Durablity
(持久性) :事務完成後,對數據庫的更改是永久保存的,不能回滾。
上面這些知識點都是反反覆覆唸叨的概念,面試必背的東西。
分佈式事務解決方案
有困難就必定會有解決問題的辦法,什麼都難不倒聰明的程序員。
XA協議
是一個基於數據庫的分佈式事務協議,其分爲兩部分:事務管理器
和本地資源管理器
。事務管理器
做爲一個全局的調度者,負責對各個本地資源管理器統一號令提交
或者回滾
。二階提交協議(2PC
)和三階提交協議(3PC
)就是根據此協議衍生出來而來。現在Oracle
、Mysql
等數據庫均已實現了XA接口
。
一、兩段提交(2PC)
兩段提交
顧名思義就是要進行兩個階段的提交:第一階段,準備階段(投票階段) ; 第二階段,提交階段(執行階段)。
上邊圖片源自網絡,若有侵權聯繫刪除
下面還拿下單扣庫存舉例子,簡單描述一下兩段提交(2PC)的原理:
以前說過業務服務化(SOA
)之後,一個下單流程就會用到多個服務,各個服務都沒法保證調用的其餘服務的成功與否,這個時候就須要一個全局的角色(協調者
)對各個服務(參與者
)進行協調。
一個下單請求過來經過協調者
,給每個參與者
發送Prepare
消息,執行本地數據腳本但不提交事務。
若是協調者
收到了參與者
的失敗消息或者超時,直接給每一個參與者
發送回滾(Rollback)
消息;不然,發送提交(Commit)
消息;參與者
根據協調者
的指令執行提交或者回滾操做,釋放全部事務處理過程當中被佔用的資源,顯然2PC
作到了全部操做要麼所有成功、要麼所有失敗。
兩段提交(2PC)的缺點
二階段提交看似可以提供原子性的操做,但它存在着嚴重的缺陷
-
網絡抖動致使的數據不一致: 第二階段中
協調者
向參與者
發送commit
命令以後,一旦此時發生網絡抖動,致使一部分參與者
接收到了commit
請求並執行,可其餘未接到commit
請求的參與者
沒法執行事務提交。進而致使整個分佈式系統出現了數據不一致。 -
超時致使的同步阻塞問題:
2PC
中的全部的參與者節點都爲事務阻塞型
,當某一個參與者
節點出現通訊超時,其他參與者
都會被動阻塞佔用資源不能釋放。 -
單點故障的風險: 因爲嚴重的依賴
協調者
,一旦協調者
發生故障,而此時參與者
還都處於鎖定資源的狀態,沒法完成事務commit
操做。雖然協調者出現故障後,會從新選舉一個協調者,可沒法解決因前一個協調者
宕機致使的參與者
處於阻塞狀態的問題。
二、三段提交(3PC)
三段提交(3PC)是對兩段提交(2PC)的一種升級優化,3PC
在2PC
的第一階段和第二階段中插入一個準備階段。保證了在最後提交階段以前,各參與者節點的狀態都一致。同時在協調者和參與者中都引入超時機制,當參與者
各類緣由未收到協調者
的commit請求後,會對本地事務進行commit,不會一直阻塞等待,解決了2PC
的單點故障問題,但3PC
仍是沒能從根本上解決數據一致性的問題。
上邊圖片源自網絡,若有侵權聯繫刪除
3PC 的三個階段分別是CanCommit
、PreCommit
、DoCommit
CanCommit:協調者向全部參與者發送CanCommit命令,詢問是否能夠執行事務提交操做。若是所有響應YES則進入下一個階段。
PreCommit:協調者
向全部參與者
發送PreCommit
命令,詢問是否能夠進行事務的預提交操做,參與者接收到PreCommit請求後,如參與者成功的執行了事務操做,則返回Yes
響應,進入最終commit階段。一旦參與者中有向協調者發送了No
響應,或因網絡形成超時,協調者沒有接到參與者的響應,協調者向全部參與者發送abort
請求,參與者接受abort命令執行事務的中斷。
DoCommit: 在前兩個階段中全部參與者的響應反饋均是YES
後,協調者向參與者發送DoCommit
命令正式提交事務,如協調者沒有接收到參與者發送的ACK響應,會向全部參與者發送abort
請求命令,執行事務的中斷。
三、補償事務(TCC)
不少初學者老是被TCC
、2PC
、3PC
這幾個概念搞混淆,傻傻分不清,實際上 TCC
與 2PC
、3PC
同樣,都只是實現分佈式事務的一種方案而已。
TCC
(Try-Confirm-Cancel)又被稱補償事務
,TCC
與2PC
的思想很類似,事務處理流程也很類似,但2PC
是應用於在DB層面,TCC則能夠理解爲在應用層面的2PC
,是須要咱們編寫業務邏輯來實現。
TCC
它的核心思想是:"針對每一個操做都要註冊一個與其對應的確認(Try)和補償(Cancel)"。
還拿下單扣庫存解釋下它的三個操做:
Try階段:
下單時經過Try操做去扣除庫存預留資源。
Confirm階段:
確認執行業務操做,在只預留的資源基礎上,發起購買請求。
Cancel階段:
只要涉及到的相關業務中,有一個業務方預留資源未成功,則取消全部業務資源的預留請求。
上邊圖片源自網絡,若有侵權聯繫刪除
TCC的缺點:
-
應用侵入性強:TCC因爲基於在業務層面,至使每一個操做都須要有
try
、confirm
、cancel
三個接口。 -
開發難度大:代碼開發量很大,要保證數據一致性
confirm
和cancel
接口還必須實現冪等性。
總結
很淺顯的介紹了一下2PC、3PC、TCC的概念,若有錯誤還望溫柔指正,分佈式事務一直都是面試中比較熱點的問題,也是進階高級Java工程師必備的知識點。
整理了幾百本各種技術電子書,有須要的同窗能夠,在我同名公衆號回覆[ 666 ]自取。技術羣快滿了,想進的同窗能夠加我好友,和大佬們一塊兒吹吹技術,期待你的加入。
不管你是剛入行、仍是已經有幾年經驗的程序員,相信這份面試提綱都會給你很多助力,長按二維碼關注 『 程序員內點事 』 ,回覆 『 offer 』 自行領取,祝你們 offer 拿到手軟