大廠面試必知必會:圖解分佈式事務實現原理

問題場景

大廠面試必知必會:圖解分佈式事務實現原理

大廠面試必知必會:圖解分佈式事務實現原理

大廠面試必知必會:圖解分佈式事務實現原理大廠面試必知必會:圖解分佈式事務實現原理

大廠面試必知必會:圖解分佈式事務實現原理

什麼是事務?

大廠面試必知必會:圖解分佈式事務實現原理

事務是數據庫從一個穩定狀態變遷到另外一個穩定狀態的保證,具有 ACID 這 4 個特性:面試

  • 原子性(Atomicity):一個事務中的全部操做,要麼所有完成,要麼所有不完成,不會結束在中間某個環節。事務在執行過程當中發生錯誤,會被回滾到事務開始前的狀態。數據庫

  • 一致性(Consistency):在事務開始以前和事務結束之後,數據庫的完整性限制沒有被破壞。安全

  • 隔離性(Isolation):兩個事務的執行是互不干擾的,兩個事務時間不會互相影響。服務器

  • 持久性(Durability):在事務完成之後,該事務對數據庫所做的更改便持久地保存在數據庫之中,而且是徹底的。

例如應用程序須要更新多條相關數據時就須要進行事務處理。網絡

什麼是分佈式事務?

當遇到複雜業務調用時,可能會出現跨庫多資源調用(一個事務管理器,多個資源)/多服務調用(多個事務管理器,多個資源),指望所有成功或失敗回滾,這就是分佈式事務,用以保證「操做多個隔離資源的數據一致性」。併發

大廠面試必知必會:圖解分佈式事務實現原理

分佈式事務與 XA 規範

分佈式事務是指會涉及到操做多個數據庫的事務,一樣必須保證 ACID。其就是將對同一庫事務的概念擴大到了對多個庫的事務:對同一庫的 SQL 操做對應了分佈式事務中對一個庫的事務。框架

X/Open XA 定義了分佈式事務處理的規範,並由數據庫廠商在驅動層面進行實現。XA 規範的基礎是兩階段提交協議,並定義了分佈式事務處理所涉及的角色:分佈式

應用程序(AP)
事務管理器(TM)
資源管理器(RM)
通訊資源管理器(CRM)ide

常見的事務管理器( TM )是交易中間件,常見的資源管理器( RM )是數據庫,常見的通訊資源管理器( CRM )是消息中間件。性能

能夠這樣認爲,事務管理器即事務處理中間件(分佈式事務處理系統);資源管理器即各個數據庫。

兩階段提交協議

大廠面試必知必會:圖解分佈式事務實現原理

兩階段提交協議(Two-phase commit protocol, 2PC)將一次分佈式事務處理劃分爲兩個階段:預提交階段(也稱爲準備階段或投票階段),提交階段。

1 預提交階段

這是兩階段提交協議的第一個階段,分佈式事務處理系統諮詢各個資源管理器是否能夠提交本地事務,各個資源管理器會把這個諮詢過程寫入日誌,以便進行回滾或提交。

當一個數據庫接收到諮詢後,它會將須要執行的操做寫入日誌,禁止其餘寫入操做(鎖定資源)。

若是分佈式事務中某數據庫預提交失敗或提交失敗,那該數據庫會根據日誌進行自身的操做回滾,並解鎖。

2 提交階段

分佈式事務處理系統對各個資源管理器下達提交/回滾的指令,使整個分佈式事務結束。

當一個數據庫接受到提交/回滾指令時,它將根據第一階段的日誌進行提交/回滾處理。

兩階段提交協議能夠在數據庫層面經過驅動支持,也能夠在應用框架中按照其原理進行設計實現。

兩階段提交協議(Two Phase Commitment Protocol)是分佈式事務的基礎協議。

在此協議中,一個事務協調器(TM, transaction manager)協調多個資源管理器(RM, resource manager)的活動;在一階段全部資源管理器(RM)向事務管理器(TM)彙報自身活動狀態,在第二階段事務管理器(TM)根據各資源管理器(RM)彙報的狀態,來決定各RM是執行提交操做仍是回滾操做;具體描述以下:

大廠面試必知必會:圖解分佈式事務實現原理

  1. 應用程序向事務管理器(TM)提交請求,發起方分佈式事務;

  2. 一階段,事務管理器(TM)聯絡全部資源管理器(RM),通知它們執行準備操做;

  3. 資源管理器(RM)返回準備成功,或者失敗的消息給TM(響應超時算做失敗);

  4. 二階段,若是全部RM均準備成功,TM會通知全部RM執行提交;若是任一RM準備失敗,TM會通知全部RM回滾;

經過事務管理器2階段協調資源管理器,使全部資源管理器的狀態最終都是一致的,要麼所有提交,要麼所有回滾。

2PC應用之XA

XA是X/Open組織提出的,定義了事務管理器與資源管理器之間通訊的接口協議;XA協議由數據庫實現,目前支持XA協議的數據庫有Oracle、MySql、BD2等;

XA定義了一系列的接口:

  • xa_start: 啓動XA事務

  • xa_end: 結束XA事務

  • xa_prepare: 準備階段,XA事務預提交

  • xa_commit:提交XA事務

  • xa_rollback: 回滾XA事務

大廠面試必知必會:圖解分佈式事務實現原理

一個數據庫實現XA協議以後,它就能夠做爲做爲一個資源管理器參與到分佈式事務中;

在一階段,事務管理器協調全部數據庫執行XA事務(xa_start、用戶SQL、xa_end),並完成XA事務預提交(xa_prepare);

在二階段,若是全部數據庫上XA事務預提交均成功,那麼事務管理器協調全部數據庫提交XA事務(xa_commit);若是任一數據庫上XA是我預提交失敗,那麼事務管理器會協調全部數據組回滾XA事務(xa_rollback);

分階段提交原理

分佈式事物基本理論: 基本遵循CPA理論,採用柔性事物特徵,軟狀態或者最終一致性特色保證分佈式事物一致性問題。

分佈式事務常看法決方案:

  1. 2PC兩段提交協議

  2. 3PC三段提交協議(彌補兩端提交協議缺點)

  3. TCC或者GTS(阿里)

  4. 消息中間件最終一致性

  5. 使用LCN解決分佈式事物,理念「LCN並不生產事務,LCN只是本地事務的搬運工」。

兩階段提交(2PC)

兩階段提交又稱2PC,2PC是一個很是經典的強一致、中心化的原子提交協議

這裏所說的中心化是指協議中有兩類節點:一個是中心化協調者節點(coordinator)和N個參與者節點(partcipant)。

兩個階段:第一階段:投票階段 和第二階段:提交/執行階段。

舉例 訂單服務A,須要調用 支付服務B 去支付,支付成功則處理購物訂單爲待發貨狀態,不然就須要將購物訂單處理爲失敗狀態。

那麼看2PC階段是如何處理的

一、第一階段:投票階段

大廠面試必知必會:圖解分佈式事務實現原理

image

第一階段主要分爲3步

1)事務詢問

協調者 向全部的 參與者 發送事務預處理請求,稱之爲Prepare,並開始等待各 參與者 的響應。

2)執行本地事務

各個 參與者 節點執行本地事務操做,但在執行完成後並不會真正提交數據庫本地事務,而是先向 協調者 報告說:「我這邊能夠處理了/我這邊不能處理」。.

3)各參與者向協調者反饋事務詢問的響應

若是 參與者 成功執行了事務操做,那麼就反饋給協調者 Yes 響應,表示事務能夠執行,若是沒有 參與者 成功執行事務,那麼就反饋給協調者 No 響應,表示事務不能夠執行。

第一階段執行完後,會有兩種可能。一、全部都返回Yes. 二、有一個或者多個返回No。

二、第二階段:提交/執行階段(成功流程)

成功條件:全部參與者都返回Yes。

大廠面試必知必會:圖解分佈式事務實現原理

第二階段主要分爲兩步

1)全部的參與者反饋給協調者的信息都是Yes,那麼就會執行事務提交

 協調者 向 全部參與者 節點發出Commit請求.

2)事務提交

 參與者 收到Commit請求以後,就會正式執行本地事務Commit操做,並在完成提交以後釋放整個事務執行期間佔用的事務資源。

第二階段:提交/執行階段(異常流程)

異常條件:任何一個 參與者 向 協調者 反饋了 No 響應,或者等待超時以後,協調者還沒有收到全部參與者的反饋響應。

大廠面試必知必會:圖解分佈式事務實現原理

異常流程第二階段也分爲兩步

1)發送回滾請求

 協調者 向全部參與者節點發出 RoollBack 請求.

2)事務回滾

 參與者 接收到RoollBack請求後,會回滾本地事務。

2PC缺點

經過上面的演示,很容易想到2pc所帶來的缺陷

1)性能問題

不管是在第一階段的過程當中,仍是在第二階段,全部的參與者資源和協調者資源都是被鎖住的,只有當全部節點準備完畢,事務 協調者 纔會通知進行全局提交,

參與者 進行本地事務提交後纔會釋放資源。這樣的過程會比較漫長,對性能影響比較大。

2)單節點故障

因爲協調者的重要性,一旦 協調者 發生故障。參與者 會一直阻塞下去。尤爲在第二階段,協調者 發生故障,那麼全部的 參與者 還都處於

鎖定事務資源的狀態中,而沒法繼續完成事務操做。(雖然協調者掛掉,能夠從新選舉一個協調者,可是沒法解決由於協調者宕機致使的參與者處於阻塞狀態的問題)

2PC出現單點問題的三種狀況

(1)協調者正常,參與者宕機

因爲 協調者 沒法收集到全部 參與者 的反饋,會陷入阻塞狀況。

 解決方案:引入超時機制,若是協調者在超過指定的時間尚未收到參與者的反饋,事務就失敗,向全部節點發送終止事務請求。

(2)協調者宕機,參與者正常

不管處於哪一個階段,因爲協調者宕機,沒法發送提交請求,全部處於執行了操做可是未提交狀態的參與者都會陷入阻塞狀況.

 解決方案:引入協調者備份,同時協調者需記錄操做日誌.當檢測到協調者宕機一段時間後,協調者備份取代協調者,並讀取操做日誌,向全部參與者詢問狀態。

(3)協調者和參與者都宕機

  1. 發生在第一階段:由於第一階段,全部參與者都沒有真正執行commit,因此只需從新在剩餘的參與者中從新選出一個協調者,新的協調者在從新執行第一階段和第二階段就能夠了。

2)發生在第二階段 而且 掛了的參與者在掛掉以前沒有收到協調者的指令。也就是上面的第4步掛了,這是可能協調者尚未發送第4步就掛了。這種情形下,新的協調者從新執行第一階段和第二階段操做。

3)發生在第二階段 而且 有部分參與者已經執行完commit操做。就比如這裏訂單服務A和支付服務B都收到協調者 發送的commit信息,開始真正執行本地事務commit,但突發狀況,Acommit成功,B確掛了。這個時候目前來說數據是不一致的。雖然這個時候能夠再經過手段讓他和協調者通訊,再想辦法把數據搞成一致的,可是,這段時間內他的數據狀態已是不一致的了!2PC 沒法解決這個問題。

三階段提交(3PC)

大廠面試必知必會:圖解分佈式事務實現原理

三階段提交協議(3PC)主要是爲了解決兩階段提交協議的阻塞問題,2pc存在的問題是當協做者崩潰時,參與者不能作出最後的選擇。所以參與者可能在協做者恢復以前保持阻塞。

三階段提交(Three-phase commit),是二階段提交(2PC)的改進版本。

與兩階段提交不一樣的是,三階段提交有兩個改動點。

一、 引入超時機制。同時在協調者和參與者中都引入超時機制。
二、在第一階段和第二階段中插入一個準備階段。保證了在最後提交階段以前各參與節點的狀態是一致的。

也就是說,除了引入超時機制以外,3PC把2PC的準備階段再次一分爲二,這樣三階段提交就有

CanCommitPreCommitDoCommit

三個階段。

一、CanCommit階段

以前2PC的一階段是本地事務執行結束後,最後不Commit,等其它服務都執行結束並返回Yes,由協調者發生commit才真正執行commit。而這裏的CanCommit指的是 嘗試獲取數據庫鎖 若是能夠,就返回Yes。

大廠面試必知必會:圖解分佈式事務實現原理

這階段主要分爲2步

事務詢問 協調者 向 參與者 發送CanCommit請求。詢問是否能夠執行事務提交操做。而後開始等待 參與者 的響應。
響應反饋 參與者 接到CanCommit請求以後,正常狀況下,若是其自身認爲能夠順利執行事務,則返回Yes響應,並進入預備狀態。不然反饋No

二、PreCommit階段

在階段一中,若是全部的參與者都返回Yes的話,那麼就會進入PreCommit階段進行事務預提交。這裏的PreCommit階段 跟上面的第一階段是差很少的,只不過這裏 協調者和參與者都引入了超時機制 (2PC中只有協調者能夠超時,參與者沒有超時機制)。

三、DoCommit階段

這裏跟2pc的階段二是差很少的。

總結

相比較2PC而言,3PC對於協調者(Coordinator)和參與者(Partcipant)都設置了超時時間,而2PC只有協調者才擁有超時機制。這解決了一個什麼問題呢?

這個優化點,主要是避免了參與者在長時間沒法與協調者節點通信(協調者掛掉了)的狀況下,沒法釋放資源的問題,由於參與者自身擁有超時機制會在超時後,

自動進行本地commit從而進行釋放資源。而這種機制也側面下降了整個事務的阻塞時間和範圍。

另外,經過CanCommit、PreCommit、DoCommit三個階段的設計,相較於2PC而言,多設置了一個緩衝階段保證了在最後提交階段以前各參與節點的狀態是一致的。

以上就是3PC相對於2PC的一個提升(相對緩解了2PC中的前兩個問題),可是3PC依然沒有徹底解決數據不一致的問題。

2PC / 3PC / XA

大廠面試必知必會:圖解分佈式事務實現原理

TCC ( Try、Confirm、Cancel ) 原理

概念

TCC三個操做描述:

Try: 檢測、預留資源;
Confirm: 業務系統執行提交;默認Confirm階段是不會出錯的,只要TRY成功,CONFIRM必定成功;
Cancel: 業務取消,預留資源釋放;

大廠面試必知必會:圖解分佈式事務實現原理

TCC又稱補償事務。其核心思想是:"針對每一個操做都要註冊一個與其對應的確認和補償(撤銷操做)"。它分爲三個操做:

一、Try階段:主要是對業務系統作檢測及資源預留。
二、Confirm階段:確認執行業務操做。
三、Cancel階段:取消執行業務操做。

TCC對應 Try、Confirm、Cancel 三種操做能夠理解成關係型數據庫事務的三種操做:DML、Commit、Rollback。

在一個跨應用的業務操做中

Try:Try操做是先把多個應用中的業務資源預留和鎖定住,爲後續的確認打下基礎,相似的,DML操做要鎖定數據庫記錄行,持有數據庫資源。

Confirm:Confirm操做是在Try操做中涉及的全部應用均成功以後進行確認,使用預留的業務資源,和Commit相似;

Cancel:Cancel則是當Try操做中涉及的全部應用沒有所有成功,須要將已成功的應用進行取消(即Rollback回滾)。其中Confirm和Cancel操做是一對反向業務操做。

TCC的具體原理圖如(盜圖):

大廠面試必知必會:圖解分佈式事務實現原理

從圖中咱們能夠明顯看到Confirm和Cancel操做是一對反向業務操做 即要try返回成功執行Confirm,要麼try返回失敗執行Cancel操做。

分佈式事務協調者:分佈式事務協調者管理控制整個業務活動,包括記錄維護TCC全局事務的事務狀態和每一個從業務服務的子事務狀態,並在業務活動提交時確認全部的TCC型

操做的confirm操做,在業務活動取消時調用全部TCC型操做的cancel操做。

舉例

例子:A服務轉30塊錢、B服務轉50塊錢,一塊兒到C服務上。

Try:嘗試執行業務。完成全部業務檢查(一致性):檢查A、B、C的賬戶狀態是否正常,賬戶A的餘額是否很多於30元,賬戶B的餘額是否很多於50元。預留必須業務資源

(準隔離性):賬戶A的凍結金額增長30元,賬戶B的凍結金額增長50元,這樣就保證不會出現其餘併發進程扣減了這兩個賬戶的餘額而致使在後續的真正轉賬操做過程當中,

賬戶A和B的可用餘額不夠的狀況。

Confirm:確認執行業務。真正執行業務:若是Try階段賬戶A、B、C狀態正常,且賬戶A、B餘額夠用,則執行賬戶A給帳戶C轉帳30元、賬戶B給帳戶C轉帳50元的轉賬

操做。 這時已經不須要作任何業務檢查,Try階段已經完成了業務檢查。只使用Try階段預留的業務資源:只須要使用Try階段賬戶A和賬戶B凍結的金額便可。

Cancel:取消執行業務釋放Try階段預留的業務資源:若是Try階段部分紅功,好比賬戶A的餘額夠用,且凍結相應金額成功,賬戶B的餘額不夠而凍結失敗,則須要

對賬戶A作Cancel操做,將賬戶A被凍結的金額解凍掉。

TCC和2PC比較

2PC是資源層面的分佈式事務,強一致性,在兩階段提交的整個過程當中,一直會持有資源的鎖。

XA事務中的兩階段提交內部過程是對開發者屏蔽的,事務管理器在兩階段提交過程當中,從prepare到commit/rollback過程當中,資源實際上一直都是被加鎖的。

若是有其餘人須要更新這兩條記錄,那麼就必須等待鎖釋放。

TCC是業務層面的分佈式事務,最終一致性,不會一直持有資源的鎖。

個人理解就是當執行try接口的時候,已經把所需的資源給預扣了,好比上面舉例的A服務已經預扣30元,B服務已經預扣50元,它是由try接口實現,這樣就保證不會

出現其餘併發進程扣減了這兩個賬戶的餘額而致使在後續的真正轉賬操做過程當中,賬戶A和B的可用餘額不夠的狀況,同時保證不會一直鎖住整個資源。(核心點應該就在這)

TCC中的兩階段提交併無對開發者徹底屏蔽,也就是說從代碼層面,開發者是能夠感覺到兩階段提交的存在。

一、try過程的本地事務,是保證資源預留的業務邏輯的正確性。

二、confirm/cancel執行的本地事務邏輯確認/取消預留資源,以保證最終一致性,也就是所謂的補償型事務

因爲是多個獨立的本地事務,所以不會對資源一直加鎖。

TCC 實質上是應用層的2PC ,比如把 XA 兩階段提交那種在數據資源層作的事務管理工做提到了數據應用層。

2PC是資源層面的分佈式事務,是強一致性,在兩階段提交的整個過程當中,一直會持有資源的鎖

TCC是業務層面的分佈式事務,最終一致性,不會一直持有資源的鎖

TCC相比較於2PC來說性能會好不少,可是由於同時須要改造try、confirm、canel3個接口,開發成本高。

注意:還有一點須要注意的是Confirm和Cancel操做可能被重複調用,故要求Confirm和Cancel兩個接口必須是冪等。

RocketMQ 分佈式事務原理

1、舉個分佈式事務場景

列子:假設 A 給 B 轉 100塊錢,同時它們不是同一個服務上。

目標:就是 A 減100塊錢,B 加100塊錢。

實際狀況可能有四種:

1)就是A帳戶減100 (成功),B帳戶加100 (成功)2)就是A帳戶減100(失敗),B帳戶加100 (失敗)3)就是A帳戶減100(成功),B帳戶加100 (失敗)4)就是A帳戶減100 (失敗),B帳戶加100 (成功)

這裏 第1和第2 種狀況是可以保證事務的一致性的,可是 第3和第4 是沒法保證事務的一致性的。

柔性事務

單數據庫事務徹底遵循ACID規範,屬於剛性事務,分佈式事務要徹底遵循ACID規範比較困難, 分佈式事務屬於柔性事務,知足BASE理論;

BASE描述:BA(Basic Availability 基本業務可用性)、S(Soft state 柔性狀態)、E(Eventual consistency 最終一致性);

柔性事務對ACID的支持:

一、原子性:嚴格遵循;

二、一致性:事務完成後的一致性嚴格遵循,事務中的一致性可適當放寬;

三、隔離性:並行事務間不可影響;事務中間結果可見性容許安全放寬;

四、持久性:嚴格遵循

爲了可用性、性能的須要,柔性事務下降了一致性(C)與隔離性(I) 的要求,即「基本可用,最終一致」.

那咱們來看下RocketMQ是如何來保證事務的一致性的。

RocketMQ 實現分佈式事務原理

RocketMQ雖然以前也支持分佈式事務,但並無開源,等到RocketMQ 4.3才正式開源。

一、基礎概念

最終一致性

RocketMQ是一種最終一致性的分佈式事務,就是說它保證的是消息最終一致性,而不是像2PC、3PC、TCC那樣強一致分佈式事務,至於爲何說它是最終一致性事務下面會詳細說明。

Half Message(半消息)

是指暫不能被Consumer消費的消息。Producer 已經把消息成功發送到了 Broker 端,但此消息被標記爲暫不能投遞狀態,處於該種狀態下的消息稱爲半消息。須要 Producer

對消息的二次確認後,Consumer才能去消費它。

消息回查

因爲網絡閃段,生產者應用重啓等緣由。致使 Producer 端一直沒有對 Half Message(半消息) 進行 二次確認。這是Brock服務器會定時掃描長期處於半消息的消息,會

主動詢問 Producer端 該消息的最終狀態(Commit或者Rollback),該消息即爲 消息回查。

二、分佈式事務交互流程

理解這張阿里官方的圖,就能理解RocketMQ分佈式事務的原理了。

大廠面試必知必會:圖解分佈式事務實現原理

咱們來講明下上面這張圖

一、A服務先發送個Half Message給Brock端,消息中攜帶 B服務 即將要+100元的信息。
二、當A服務知道Half Message發送成功後,那麼開始第3步執行本地事務。
三、執行本地事務(會有三種狀況一、執行成功。二、執行失敗。三、網絡等緣由致使沒有響應)
4.1)、若是本地事務成功,那麼Product像Brock服務器發送Commit,這樣B服務就能夠消費該message。4.2)、若是本地事務失敗,那麼Product像Brock服務器發送Rollback,那麼就會直接刪除上面這條半消息。4.3)、若是由於網絡等緣由遲遲沒有返回失敗仍是成功,那麼會執行RocketMQ的回調接口,來進行事務的回查。

從上面流程能夠得知 只有A服務本地事務執行成功 ,B服務才能消費該message

而後咱們再來思考幾個問題?

爲何要先發送Half Message(半消息)

我以爲主要有兩點

1)能夠先確認 Brock服務器是否正常 ,若是半消息都發送失敗了 那說明Brock掛了。
2)能夠經過半消息來回查事務,若是半消息發送成功後一直沒有被二次確認,那麼就會回查事務狀態。

什麼狀況會回查

也會有兩種狀況

1)執行本地事務的時候,因爲忽然網絡等緣由一直沒有返回執行事務的結果(commit或者rollback)致使最終返回UNKNOW,那麼就會回查。
2) 本地事務執行成功後,返回Commit進行消息二次確認的時候的服務掛了,在重啓服務那麼這個時候在brock端   它仍是個Half Message(半消息),這也會回查。

特別注意: 若是回查,那麼必定要先查看當前事務的執行狀況,再看是否須要從新執行本地事務。

想象下若是出現第二種狀況而引發的回查,若是不先查看當前事務的執行狀況,而是直接執行事務,那麼就至關於成功執行了兩個本地事務。

爲何說MQ是最終一致性事務

經過上面這幅圖,咱們能夠看出,在上面舉例事務不一致的兩種狀況中,永遠不會發生

A帳戶減100 (失敗),B帳戶加100 (成功)

由於:若是A服務本地事務都失敗了,那B服務永遠不會執行任何操做,由於消息壓根就不會傳到B服務。

那麼 A帳戶減100 (成功),B帳戶加100 (失敗) 會不會可能存在的。

答案是會的

由於A服務只負責當我消息執行成功了,保證消息可以送達到B,至於B服務接到消息後最終執行結果A並無論。

那B服務失敗怎麼辦?

若是B最終執行失敗,幾乎能夠判定就是代碼有問題因此才引發的異常,由於消費端RocketMQ有重試機制,若是不是代碼問題通常重試幾回就能成功。

若是是代碼的緣由引發屢次重試失敗後,也沒有關係,將該異常記錄下來,由人工處理,人工兜底處理後,就可讓事務達到最終的一致性。

相關文章
相關標籤/搜索