淺析分佈式事務中的2PC和3PC

分佈式事務

大型的分佈式系統架構都會涉及到事務的分佈式處理的問題,基原本說,分佈式事務和普通事務都有一個共同原則:數據庫

  • A(Atomic) 原子性,事務要麼一塊兒完成,要麼一塊兒回滾
  • C(Consistent) 一致性,提交數據先後數據庫的完整性不變
  • I(Isolation) 隔離性,不一樣的事務相互獨立,不互相影響
  • D(Duration)持久性,數據狀態是永久的

另一個設計原則,分佈式系統要符合如下原則:網絡

  • C(Consistent)一致性,分佈式系統中存在的多個副本,在數據和內容上要如出一轍
  • A(Availability)高可用性,在有限時間內保證系統響應
  • P(Partition tolerance)分區容錯性,一個副本或一個分區出現宕機或其餘錯誤時,不影響系統總體運行

因爲在設計分佈式系統時,難以保證CAP所有符合,最多保證其中兩個,例如在一個分佈式系統中:
要保證系統數據庫的強一致性,須要跨表跨庫佔用數據庫資源,在複雜度比較高的狀況下,耗時難以保證,就會出現可用性沒法保證的狀況。架構

故而又出現了BASE理論異步

  • Basic Available基本可用,分佈式系統在出現故障時,容許損失部分可用功能,保證核心功能可用
  • Soft state柔性狀態,容許系統存在中間狀態,這個狀態不影響系統可用性
  • Eventually Consistent 最終一致性 指通過一段時間以後,全部數據狀態保持一致的結果

實際上BASE理論是基於AP的一個擴展,一個分佈式事務不須要強一致性,只須要達到一個最終一致性就能夠了。分佈式

分佈式事務就是處理分佈式中各個節點的數據操做,使之可以在節點相互隔離的狀況下完成多個節點數據的一致性操做。性能

分步式事務 - 2PC

2PC即二階段提交,在這裏須要瞭解兩個概念spa

  • 參與者:參與者即各個實際參與事務的節點,這些節點相互隔離,彼此不知道對方是否提交事務。
  • 協調者:收集和管理參與者的事務信息,負責統一管理節點信息,也就是分佈式事務中的第三方。

準備階段,也稱投票階段

準備階段中,協調者向參與者發送precommit的消息,參與者在本地執行事務邏輯,若是沒有超時以及運行無誤,那麼會記錄redo和undo日誌,將ack信息發送給協調者,當協調者收到全部節點參與者發送的ack信息時,準備進入下一階段,不然會發送回滾信息給各個節點,各個節點根據以前記錄好的undo信息回滾,本次事務提交失敗。設計

提交階段

提交階段中,協調者已經收到全部節點的應答信息,接下來發送commit消息給各個節點,通知各個節點參與者能夠提交事務,各個參與者提交完畢後一一發送完成信息給協調者,並釋放本地佔用的資源,協調者收到全部完成消息後,完成事務。日誌

二階段提交的圖示以下:
圖片描述中間件

二階段提交的問題

二階段提交雖然可以解決大多數的分佈式事務的問題,且發生數據錯誤的機率極小,但仍然有如下幾個問題:

  • 單點故障:若是協調者宕機,那麼參與者會一直阻塞下去,若是在參與者收到提交消息以前協調者宕機,那麼參與者一直保持未成功提交的狀態,會一直佔用資源,致使同時間其餘事務可能要一直等待下去。
  • 同步阻塞問題:由於參與者是在本地處理的事務,是阻塞型的,在最終commit以前,一直佔用鎖資源,若是遇到時間較長而協調者未發回commit的狀況,那麼會致使鎖等待。
  • 數據一致性問題:假如協調者在第二階段中,發送commit給某些參與者失敗,那麼就致使某些參與者提交了事務,而某些沒有提交,這就致使了數據不一致。
  • 二階段根本沒法解決的問題:假如協調者宕機的同時,最後一個參與者也宕機了,當協調者經過從新選舉再參與到事務管理中時,它是沒有辦法知道事務執行到哪一步的。

針對於以上提出的一些問題,衍生出了3PC。

分佈式事務 - 3PC

3PC即三階段提交協議。

圖片描述

3PC相對於2PC,有了如下變化:

  • 引入超時機制,在參與者和協調者中都加入了各自的超時策略。
  • 加入了一個新的階段,canCommit,因此階段分紅了三個:canCommit、PreCommit、DoCommit。

CanCommit

這是一個準備階段,在這一階段中,協調者向參與者發送CanCommit消息,參與者接收後,根據自身資源狀況判斷是否能夠執行事務操做,若是能夠而且未超時,則發送yes給協調者,反之,協調者會中斷事務。

PreCommit

這是預備階段,在這一階段中,協調者向參與者發送PreCommit消息,參與者接收後,會執行事務操做,記錄undo和redo日誌,事務執行完畢後會將Ack消息發送給協調者,協調者在未超時的狀況下收集全部參與者的信息,不然中斷事務,通知全部參與者Abort消息。

DoCommit

當全部參與者Ack消息完畢以後,協調者會確認發送DoCommit消息給每個參與者,執行提交事務。原則上全部參與者執行提交完畢以後,須要發送Committed給協調者,協調者完成事務。不然協調者中斷事務,參與者接收abort消息會根據以前記錄的undo回滾。
但也要注意,此階段中若是參與者沒法及時收到協調者發來的Docommit消息時,也會自行提交事務,由於從機率上來說,PreCommit這個階段可以不被abort說明所有節點均可以正常執行事務提交,因此通常來說單個節點提交不影響數據一致性,除非極端狀況。

2PC 和 3PC的區別

相對於2PC,3PC主要解決的單點故障問題,並減小阻塞,由於一旦參與者沒法及時收到來自協調者的信息以後,他會默認執行commit。而不會一直持有事務資源並處於阻塞狀態。可是這種機制也會致使數據一致性問題,由於,因爲網絡緣由,協調者發送的abort響應沒有及時被參與者接收到,那麼參與者在等待超時以後執行了commit操做。這樣就和其餘接到abort命令並執行回滾的參與者之間存在數據不一致的狀況。

消息中間件

上面提到的關於協調者在實踐過程當中由誰來擔任是個問題,通常來說這個協調者是異步的,能夠在參與者和協調者之間雙向通訊的,有良好的消息傳遞機制,可以保證消息穩定投遞。故而通常協調者的擔任者是高性能的消息中間件例如RocketMq、Kafka、RabbitMq等。

如圖就是一個2PC的實踐:
圖片描述

相關文章
相關標籤/搜索