事務咱們都不陌生,咱們常說的事務通常都是指單機事務,即本地事務。那分佈式事務是什麼?分佈式事務就是由多個本地事務組合而成的事務,通常在分佈式場景下才會出現。程序員
好比電商平臺中,咱們在購物的時候,下單支付這個過程看上去是一鼓作氣的,可是背後多是多個系統的分工合做。訂單系統、支付系統、物流系統等。這些系統部署在不一樣的服務器上,執行的都是各類的事務,對於電商平臺來講,這就是分佈式事務。算法
本地事務都好解決,有一套現成的事務機制,分佈式事務比本地事務就要複雜多。如何實現分佈式事務呢?大概有 3 種解決方式:數據庫
XA協議由 Tuxedo 首先提出的,並交給X/Open組織,做爲資源管理器(數據庫)與事務管理器的接口標準。目前,Oracle、Informix、DB2和Sybase等各大數據庫廠家都提供對XA的支持。----來源百度百科服務器
二階段提交也叫 2PC ,The two-phase commit protocol。首先在二階段提交中有兩個角色:網絡
所謂得兩階段提交就是指投票(voting)和提交(commit) 兩個階段,跟選舉制度同樣,先投票,再決定。異步
投票階段,協調者向參與者發起執行事務操做的請求(CanCommit 請求),並等待參與者響應。分佈式
參與者接受到請求後,執行事務請求操做,記錄日誌信息但不提交,記錄成功後,向協調者發生 「Yes」 消息,表示贊成提交操做,若不成功,則發送「No」 消息,表示不一樣意此次操做。注意這個過程會鎖定數據。性能
投票階段得流程圖,大概就是下面這樣子:大數據
提交階段,協調者接受到全部參與者的響應以後,根據返回來的信息狀況,向參與者發送提交或回滾請求。日誌
若收到的響應消息都是 「Yes」,則向參與者發送 「DoCommit」 消息,參與者完成本地事務的其餘操做並釋放資源,而後向協調者發送 「HaveCommitted」消息;
若是協調者收到的消息中包含「No」消息或者在規定時間內有參與者沒有響應,則向全部參與者發送「DoAbort」消息,此時發送「Yes」的參與者則會根據以前執行操做時的回滾日誌對操做進行回滾,而後全部參與者會向協調者發送「HaveCommitted」消息;
提交階段的流程,大概入下圖所示:
二階段提交協議容易理解,基於 XA 的二階段提交算法知足事務的 ACID 特性,看上去比較完美,可是缺點仍是挺多的,主要有如下幾個問題:
三階段提交協議(Three-phase commit protocol,3PC)是對二階段提交(2PC)的改進。解決了二階段提交的一些問題,三階段和二階段提交最大的不一樣是引入超時機制和準備階段。
先來講說超時機制,在二階段提交,只有協調者纔有超時機制,若是協調者在規定時間內沒有接收到參與者的響應,就會根據當前狀態提交或者終止整個事務,可是若是協調者掛了,參與者並無超時機制,因此就一直等待,這也是二階段提交單點故障的問題。在三階段提交中,同時在協調者和參與者中引入超時機制。若是協調者或參與者在規定的時間內沒有接收到來自其餘節點的響應,就會根據當前的狀態選擇提交或者終止整個事務。
三階段提交其實就是將二階段提交中的提交階段一分爲二,三階段提交協議中的具體三階段是:CanCommit、PreCommit、DoCommit 三個階段
CanCommit 階段,CanCommit 階段與 2PC 的投票階段相似:協調者向參與者發送請求操做(CanCommit 請求),詢問參與者是否能夠執行事務提交操做,而後等待參與者的響應;參與者收到 CanCommit 請求以後,回覆 Yes,表示能夠順利執行事務;不然回覆 No。
PreCommit 階段,根據二階段提交中的提交階段類似,根據 CanCommit 階段返回的結果,來決定是否能夠進行 PreCommit 操做。
這時候就存在兩種狀況,若是全部參與者都回覆 「Yes」,那麼執行流程是這樣的:
若是有參與者返回 「No」,或者協調者在規定時間內沒有收到參與者的響應,那麼將執行中斷事務操做。流程是這樣的:
DoCommit 階段, 事務真正提交階段,協調者根據 PreCommit 階段參與者返回來的信息,決定是進入提交階段仍是事務中斷階段。
提交階段流程以下:
事務中斷階段,流程以下:
不論是二階段提交仍是三階段提交,都屬於強一致性的,知足事務的 ACID 原則。它們都有兩個共同的問題:
而基於 MQ 消息的分佈式解決方案就不太同樣了,它採用的不是強一致性,而是最終一致性,這也就是 BASE 理論。而且咱們直到 MQ 是異步的,因此性能也比較快,能夠說完美的解決了上面兩種方式帶來的問題。
基於 MQ 消息中間件解決分佈式事務的思路是這樣的:主要是基於 MQ 消息投遞的可靠性,將分佈式事務發送給 MQ 中間件以後,中間件將事務持久化,這一點很是重要,保證消息不丟失。消費者端異步消費,若是遇到失敗狀況,因爲咱們的消息是持久化的,因此能夠根據業務規則不斷重試,有必要的話,人工補償,保證數據最終一致性。
關於基於分佈式消息的最終一致性方案,我準備基於 RocketMQ 單獨開一個章節,詳細聊一聊,這裏就很少說了。
歡迎關注公衆號【互聯網平頭哥】。關注這個互聯網苟且偷生的程序員,願你我共同進步,今天最好的是明天最低的要求。