分散式事務總結

luocj_發表於2019-02-19

事務

事務的定義

事務提供一種機制將一個活動涉及的所有操作納入到一個不可分割的執行單元,組成事務的所有操作只有在所有操作均能正常執行的情況下方能提交,只要其中任一操作執行失敗,都將導致整個事務的回滾。簡單地說,事務提供一種"要麼什麼都不做,要麼做全套(All or Nothing)"機制。

資料庫本地事務

ACID

1. Atomicity 原子性

    程式碼要麼全部完成,要麼全部不完成。

2. Consistency 一致性

    事務執行成功,那麼所有變化(一般指資料)均正確操作。

3. Isolation 隔離性

    在併發環境下,不同事務操作相同資料,每個事務都有各自完整的資料空間。事務不會檢視到中間資料。

4. Durability 永續性

    事務只要成功結束,那麼對資料庫資料的更新便會永久儲存下來。

InnoDB實現原理

1. InnoDB 是 mysql 的一個儲存引擎。

2. 事務的 ACID 是透過 InnoDB 的日誌和鎖來保證的。

    1. 隔離性透過資料庫鎖來保證。

    2. 原子性和一致性透過UndoLog來保證。

       1. UndoLog:在操作任何資料前,將資料備份到一個地方(資料儲存備份的地方叫做UndoLog)。然後進行修改,如果事務執行失敗了,那麼系統可以利用備份資料恢復到事務執行前的狀態。

    3. 永續性透過RedoLog來保證。

       1. RedoLog:記錄新資料的備份,在事務提交前,只要將RedoLog持久化即可,不需要將資料持久化。當系統崩潰時,系統會根據RedoLog的內容,將資料更新至最新狀態。

分散式事務

分散式事務的定義

一次大的操作由不同的小的操作組成,而不同的小操作在不同的伺服器或者容器內。分散式事務需要保證這些小操作要麼全部成功,要麼全部失敗。

為什麼要使用分散式事務

1. 微服務與SOA等服務架構的興起

2. 單機不能滿足業務需要

3. 資料量太大,導致需要分庫分表,分佈在不同機房

分散式事務的基礎

CAP

CAP定理又稱布魯爾定理,這三者不可兼得。

1. C Consistency 一致性

    所有資料備份,在同一時刻是否同樣的值

2. A Availability 可用性

    叢集中的部分節點出現故障,叢集整體是否還能相應客戶端讀寫

3. P Partition tolerance 分割槽容錯性

    分割槽相當於對通訊的時限要求,系統如果不能在指定時限內達成資料一致性,就意味著發生了分割槽,需要在 C 與 A 之間選擇。

CAP三者不能共有。

1. CA 理論上不可能存在。由於網路無法100%可靠,故分散式系統中必定會有分割槽。分割槽發生時,為了保證 C,這個時候一定要拒絕請求,但是 A 不允許。

2. CP 放棄可用性,追求強一致

3. AP 放棄一致性(強一致性),追求分割槽容錯性和可用性。BASE也是根據 AP 的擴充

BASE

1. Basically Available 基本可用

   分散式系統在出現故障時,允許損失部分可用功能,保證核心功能可用。

2. Soft state 軟狀態

    允許系統中存在中間狀態,這個狀態不影響系統可用性,這裡指的是CAP中的不一致。

3. Eventually consistent 最終一致性

    最終一致是指經過一段時間後,所有節點資料都將會達到一致。

BASE解決了CAP中理論沒有網路延遲,在BASE中用軟狀態和最終一致,保證了延遲後的一致性。BASE和 ACID 是相反的,它完全不同於ACID的強一致性模型,而是透過犧牲強一致性來獲得可用性,並允許資料在一段時間內是不一致的,但最終達到一致狀態。

分散式事務的解決方案

2PC

第一階段:事務管理器要求每個涉及到事務的資料庫預提交(precommit)此操作,並反映是否可以提交.

第二階段:事務協調器要求每個資料庫提交資料,或者回滾資料。

優點

1. 儘量保證了資料的強一致,實現成本較低,在各大主流資料庫都有自己實現,對於MySQL是從5.5開始支援。

缺點

1. 單點問題:事務管理器在整個流程中扮演的角色很關鍵,如果其當機,比如在第一階段已經完成,在第二階段正準備提交的時候事務管理器當機,資源管理器就會一直阻塞,導致資料庫無法使用。

2. 同步阻塞:在準備就緒之後,資源管理器中的資源一直處於阻塞,直到提交完成,釋放資源。

3. 資料不一致:兩階段提交協議雖然為分散式資料強一致性所設計,但仍然存在資料不一致性的可能,比如在第二階段中,假設協調者發出了事務commit的通知,但是因為網路問題該通知僅被一部分參與者所收到並執行了commit操作,其餘的參與者則因為沒有收到通知一直處於阻塞狀態,這時候就產生了資料的不一致性。

TCC

1. Try階段:嘗試執行,完成所有業務檢查(一致性),預留必須業務資源(準隔離性)

2. Confirm階段:確認執行真正執行業務,不作任何業務檢查,只使用Try階段預留的業務資源,Confirm操作滿足冪等性。要求具備冪等設計,Confirm失敗後需要進行重試。

3. Cancel階段:取消執行,釋放Try階段預留的業務資源 Cancel操作滿足冪等性Cancel階段的異常和Confirm階段異常處理方案基本上一致。

與2PC區別

1. 2pc 和3pc 是依靠mysql xa 實現的,是db 層實現(就是直連mysql),tcc 業務層實現符合soa理念,解耦。

2. TCC屬於業務上的分段提交,Try,confirm,cancel都是對應的一段業務邏輯的操作,先預留資源,預留成功後進行確認,不成功就取消,例如轉賬先凍結資金,進行一系列的餘額各方面的檢查,發現符合條件就對賬戶對應的資金狀態改為凍結,確認階段修改狀態為扣除,取消的話就把凍結的資金加回原賬戶,其對應的資料庫的操作每段都是一個完整的事物;2PC是屬於資料庫層面的,先進行prepare,然後逐個進行commit或者rollback,不和具體業務邏輯掛鉤,TCC的應用範圍更廣,不一定是事物關聯式資料庫,也可能操作的KV資料庫,文件資料庫,粒度也可以隨著具體業務靈活調整,效能更好。

本地訊息表

此方案的核心是將需要分散式處理的任務透過訊息日誌的方式來非同步執行。

對於本地訊息佇列來說核心是把大事務轉變為小事務。用100元去買一瓶水的例子。

1. 當你扣錢的時候,你需要在你扣錢的伺服器上新增加一個本地訊息表,你需要把你扣錢和寫入減去水的庫存到本地訊息表放入同一個事務(依靠資料庫本地事務保證一致性。

2. 這個時候有個定時任務去輪詢這個本地事務表,把沒有傳送的訊息,扔給商品庫存伺服器,叫他減去水的庫存,到達商品伺服器之後這個時候得先寫入這個伺服器的事務表,然後進行扣減,扣減成功後,更新事務表中的狀態。

3. 商品伺服器透過定時任務掃描訊息表或者直接通知扣錢伺服器,扣錢伺服器本地訊息表進行狀態更新。

4. 針對一些異常情況,定時掃描未成功處理的訊息,進行重新傳送,在商品伺服器接到訊息之後,首先判斷是否是重複的,如果已經接收,在判斷是否執行,如果執行在馬上又進行通知事務,如果未執行,需要重新執行需要由業務保證冪等,也就是不會多扣一瓶水。

本地訊息佇列是BASE理論,是最終一致模型,適用於對一致性要求不高的。實現這個模型時需要注意重試的冪等。

MQ事務

RocketMQ 對 MQ 事務進行了封裝。具體內容可以參考連結。

RocketMQ 4.3 正式釋出,支援分散式事務

Saga事務

Saga其實是30年前的一篇資料庫論文裡提到的一個概念。在論文中一個Saga事務就是一個長期執行的事務,這個事務是由多個本地事務所組成, 每個本地事務有相應的執行模組和補償模組,當saga事務中的任意一個本地事務出錯了, 可以透過呼叫相關事務對應的補償方法恢復,達到事務的最終一致性。

具體可以看以下連結:

Saga分散式事務解決方案與實踐

來源:

再有人問你分散式事務,把這篇扔給他

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章