事務理論/分佈式事務一致性【小總結】

1、事務相關理論

目前關於事務的幾大理論包括:ACID特性(數據庫的特性),CAP分佈式理論,以及BASE等。數據庫

  • 事務的ACID特性:數據庫
  • 事務的CAP分佈式理論、BASE:分佈式事務

事務的ACID特性

一、A(原子性):一個事務包含多個操做,這些操做要麼所有執行,要麼全都不執行;實現事務的原子性,要支持回滾操做,在某個操做失敗後,回滾到事務執行以前的狀態。網絡

二、C(一致性):一致性是指事務使得系統從一個一致的狀態轉換到另外一個一致狀態,保證數據的完整性。事務的一致性決定了一個系統設計和實現的複雜度,也致使了事務的不一樣隔離級別。併發

三、I(隔離性):保證事務不受外部併發操做,在獨立環境執行。多個併發的事務同時訪問一個數據庫時,一個事務不該該被另外一個事務所幹擾,每一個併發的事務間要相互進行隔離。框架

四、D(持久性):指一個事務一旦被提交了,那麼對數據庫中的數據的改變是永久的,即使是在數據庫系統遇到故障的狀況下也不會丟失提交事務的操做。異步

事務的CAP理論

一、C(一致性):在分佈式環境下,一致性是指多個節點數據是否一致;分佈式

二、A(可用性):服務一直保持可用的狀態,當用戶發出一個請求,服務能在必定的時間內返回結果;不少中間件或者開源框架都支持高可用方案(Redis、Zookeeper等);性能

三、P(分區容忍性):特指對網絡分區的容忍性;分佈式系統在遇到任何的 網絡分區(分佈式系統中不一樣節點部署在不同的網絡環境) 故障的時候,仍然須要保證對外提供知足一致性和可用性的服務設計

BASE

BA: Basic Availability 基本業務可用性;日誌

S: Soft state 柔性狀態;中間件

E: Eventual consistency 最終一致性;

2、事務的隔離性

一、在事務併發操做時,可能出現的問題有以下三種:

  • 髒讀:事務A修改了一個數據,但未提交,事務B讀到了事務A未提交的更新結果,若是事務A提交失敗,事務B讀到的就是髒數據
  • 不可重複讀:在同一個事務中,對於同一份數據讀取到的結果不一致。好比,事務B在事務A提交前讀到的結果,和提交後讀到的結果可能不一樣。不可重複讀出現的緣由就是事務併發修改記錄,要避免這種狀況,最簡單的方法就是對要修改的記錄加鎖,這回致使鎖競爭加重,影響性能。另外一種方法是經過MVCC能夠在無鎖的狀況下,避免不可重複讀。

補充 MVCC:多版本併發控制。是一種併發控制的方法,你們應該知道,鎖機制能夠控制併發操做,可是系統開銷比較大(悲觀鎖),而MVCC(樂觀鎖)能夠在大多數狀況下代替行級鎖,能夠下降系統開銷。 在MYSQL中,MyISAM使用的是表鎖,InnoDB使用的是行鎖。而InnoDB的事務分爲四個隔離級別,其中默認的隔離級別REPEATABLE READ須要兩個不一樣的事務相互之間不能影響,並且還能支持併發,這點悲觀鎖是達不到的,因此REPEATABLE READ採用的就是樂觀鎖,而樂觀鎖的實現採用的就是MVCC。正是由於有了MVCC,才造就了InnoDB強大的事務處理能力

樂觀鎖讀寫事務,在真正的提交以前,不加讀/寫鎖,而是先看一下數據的版本/時間戳,等到真正提交的時候再看一下版本/時間戳,若是兩次相同,說明別人期間沒有對數據進行過修改,那麼就能夠放心提交

  • 幻讀:在同一個事務中,同一個查詢屢次返回的結果不一致。事務A新增了一條記錄,事務B在事務A提交先後各執行了一次查詢操做,發現後一次比前一次多了一條記錄。幻讀是因爲併發事務增長記錄致使的,這個不能像不可重複讀經過記錄加鎖解決,由於對於新增的記錄根本沒法加鎖。須要將事務串行化,才能避免幻讀

二、針對事務併發致使的問題,經過事務隔離來解決,事務隔離級別從低到高以下:

  • 讀未提交:顧名思義,就是能夠讀到未提交的內容。一個事務能夠讀到另外一個事務未提交的結果。上述全部的併發事務問題都會發生。如無特殊狀況,基本是不會使用這種隔離級別的。
  • 讀提交:只有在事務提交後,其更新結果纔會被其餘事務看見。能夠解決髒讀問題。
  • 可重複讀:在一個事務中,對於同一份數據的讀取結果老是相同的,不管是否有其餘事務對這份數據進行操做,以及這個事務是否提交。能夠解決髒讀、不可重複讀。
  • 串行化:事務串行化執行,隔離級別最高,犧牲了系統的併發性。能夠解決併發事務的全部問題。

一般,在項目爲了性能的考慮會對隔離性進行折中

3、事務的一致性

  • 強一致性:讀操做能夠當即讀到提交的更新操做
  • 弱一致性:提交的更新操做,不必定當即會被讀操做讀到,此種狀況會存在一個不一致窗口,指的是讀操做能夠讀到最新值的一段時間
  • 最終一致性:是弱一致性的特例。事務更新一份數據,最終一致性保證在沒有其餘事務更新一樣的值的話,最終全部的事務都會讀到以前事務更新的最新值。若是沒有錯誤發生,不一致窗口的大小依賴於:通訊延遲,系統負載等

4、分佈式事務的實現:兩階段提交(2PC)和三階段提交(3PC)【XA協議】

一、兩階段提交:

在兩階段提交中,系統分爲兩類節點:協調者和參與者

(1)請求階段(決策階段):協調者將通知事務參與者準備提交或取消事務,而後進入表決過程;在表決過程當中,參與者將告知協調者本身的決策:贊成(事務參與者本地做業執行成功)或取消(本地做業執行故障)

(2)提交階段:在該階段,協調者將基於第一個階段的投票結果進行決策:提交或取消。 當且僅當全部的參與者贊成提交事務協調者才通知全部的參與者提交事務,不然協調者將通知全部的參與者取消事務。 參與者在接收到協調者發來的消息後將執行響應的操做

缺點:

  • 同步阻塞問題:執行過程當中,全部的節點都是事務阻塞的;
  • 數據不一致:在兩階段提交的第二階段中,當協調者向參與者發送commit請求後,因爲網絡緣由或者在發送commit請求過程當中協調者發生了故障,只有一部分參與者收到了commit請求,而且執行提交操做,其餘參與者沒法執行事務提交,最後致使整個分佈式系統的數據不一致

全部兩階段提交沒法解決的問題就是:沒法保證事務執行的完整性(數據的一致性)

二、三階段提交:

與兩階段提交協議的區別:三階段提交協議在協調者和參與者之間引入了超時機制; 在2PC的準備階段和提交階段之間,插入預提交階段,使3PC擁有CanCommit、PreCommit、DoCommit三個階段。 PreCommit是一個緩衝,保證了在最後提交階段以前各參與節點的狀態是一致的

(1)CanCommit階段:3PC的CanCommit階段其實和2PC的準備階段很像。 協調者向參與者發送commit請求,參與者響應是否能夠提交。

(2)PreCommit階段:協調者根據參與者的響應狀況來決定是否能夠繼續事務的PreCommit操做

  • 若是全部參與者的(canCommit)響應都是能夠提交,那麼就會執行事務的預執行;1)發送預提交請求:協調者向參與者發送preCommit請求,並進入prepared階段;2)事務預提交:參與者接收PreCommit請求後,會執行事務操做,並將undo和redo信息記錄到事務日誌中;3)響應反饋:若是參與者成功地執行了事務操做,則返回ACK響應,同時開始等待最終指令。
  • 若是有任何一個參與者響應是不能夠提交,或者等待超時以後,協調者都沒有收到參與者的響應,那麼就會中斷事務;1)發送中斷請求:協調者向全部參與者發送中斷請求;2)中斷事務:參與者收到協調者發送過來的中斷請求以後,或者超時以後,尚未收到參與者的響應,那麼會執行事務的中斷

(3)DoCommit階段:該階段進行真正的事務提交

  • 執行提交:1)發送提交請求:協調者收到參與者發送的ACK響應(PreCommit),那麼他將從預提交狀態進入提交狀態,並向全部參與者發送DoCommit請求;2)事務提交:參與者接收到doCommit請求以後執行正式的事務提交。並在完成事務提交以後釋放全部事務資源;3)響應反饋:事務提交完以後,向協調者發送ACK響應;4)完成事務:協調者接收到全部參與者的ACK響應以後,完成事務
  • 中斷事務:協調者沒有接收到參與者發送的ACK響應(多是接受者發送的不是ACK響應,也可能響應超時),那麼就會執行中斷事務

缺點:若是進入PreCommit後,協調者發出的是abort請求,假設只有一個參與者收到並進行了abort操做, 而其餘對於系統狀態未知的參與者會根據3PC選擇繼續Commit,此時系統狀態發生不一致性

小總結:

分佈式系統的一個難點就是:「網絡通訊的不可靠」,只能經過「確認機制」、「重試機制」、「補償機制」等各方面來解決一些問題。在綜合考慮可用性、性能、實現複雜度等各方面的狀況上,比較好的選擇是「異步確保最終一致性」(確認機制),只是具體實現方式上有一些差別

相關文章
相關標籤/搜索