1. 程式人生 > >利用mq的最終一致性,解決分散式事務。

利用mq的最終一致性,解決分散式事務。

 我們的訂單系統和商品(庫存)是兩個系統,當我們下訂單後,我們就要去修改庫存。

分散式系統要滿足cap定理。一致性,可靠性,可用性。

我們沒法都滿足,只能滿足兩個。因為我們是電商專案。我們要滿足服務的高可用。所以我們滿足可靠性,和可用性。但是,我們又得滿足一致性,這個時候,這個矛盾的解決又要依靠base理論中的最終一致性。我們無法滿足強一致,但是我們可以滿足最終一致性。

在電商系統中,我們用mq來保證最終一致性。保證mq一定會被消費。保證mq會被消費,我們主要有ack機制和序列化機制。

補充知識:

https://my.oschina.net/floor/blog/1587537

https://blog.csdn.net/hu_zhiting/article/details/77164138


分散式事務及解決方案

1、 經典事務

經典事務,是指傳統的單機資料庫事務,必須具備ACID原則:

原子性(A

所謂的原子性就是說,在整個事務中的所有操作,要麼全部完成,要麼全部不做,沒有中間狀態。對於事務在執行中發生錯誤,所有的操作都會被回滾,整個事務就像從沒被執行過一樣。

一致性(C

事務的執行必須保證系統的一致性,就拿轉賬為例,A500元,B300元,如果在一個事務裡A成功轉給B50元,那麼不管併發多少,不管發生什麼,只要事務執行成功了,那麼最後A賬戶一定是450元,B賬戶一定是350元。

隔離性(I

所謂的隔離性就是說,事務與事務之間不會互相影響,一個事務的中間狀態不會被其他事務感知。

永續性(

D

所謂的永續性,就是說一單事務完成了,那麼事務對資料所做的變更就完全儲存在了資料庫中,即使發生停電,系統宕機也是如此。

2、 分散式事務

2.1、 什麼是分散式事務

事務發生時,其中的參與者主要包含:應用服務、資料庫。在經典事務中,無論是應用服務還是資料庫都是單機部署,因此可以完全遵循ACID原則。但是現在主流的系統架構都是SOA的架構,以及現在日漸火熱的微服務架構中,應用及資料庫都會採用分散式叢集部署。於是就產生了跨資料來源或者跨服務的事務,這就是分散式事務。

A系統 開啟事務,下單

B系統 開啟事務,減庫存

C系統 --mysql | Oracle

2.2、 解決分散式事務的思路

在分散式系統中,就不得不面對

CAP的理論。

CAP定理是由加州大學伯克利分校Eric Brewer教授提出來的,他指出WEB服務無法同時滿足一下3個屬性:

· 一致性(Consistency) : 客戶端知道一系列的操作都會同時發生(生效)

· 可用性(Availability) : 每個操作都必須以可預期的響應結束

· 分割槽容錯性(Partition tolerance) : 即使出現單個元件無法可用,操作依然可以完成

具體地講在分散式系統中,在任何資料庫設計中,一個Web應用至多隻能同時支援上面的兩個屬性。顯然,任何橫向擴充套件策略都要依賴於資料分割槽。因此,設計人員必須在一致性與可用性之間做出選擇。

AP –> 犧牲C (最終一致性

而面對高併發的網際網路行業,高可用顯然會比一致性要重要的多,但是一致性也是不可拋棄的,如何解決這一矛盾?這個時候,大神們有總結出了BASE理論

· Basically Available(基本可用)

· Soft state(軟狀態)

· Eventually consistent(最終一致性)

BASE理論是對CAP中的一致性和可用性進行一個權衡的結果,理論的核心思想就是:我們無法做到強一致,但每個應用都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性Eventual consistency)。

2.3、 柔性事務和剛性事務

剛性事務:嚴格遵循ACID原則的事務, 例如單機環境下的資料庫事務。

柔性事務:指遵循BASE理論(基本可用,最終一致)的事務, 通常用在分散式環境中。

因為分散式事務的特點,只能採用柔性事務,常用的柔性事務解決方案有:

兩階段提交(Two Phase Commit, 2PC

有成熟的解決框架,實現簡單。

資源鎖定週期長,執行效率低,不適合高併發場景

故障恢復困難

u TCC補償型事務(Try-Confirm-Cancle

實現很複雜,開發成本高

資源鎖定粒度小,執行效率高

強隔離性,嚴格的資料一致性

事務執行週期短

非同步確保,基於可靠MQ服務

實現較為複雜,成本略高

MQ的可靠性要求高

事務執行週期長

最大努力通知

實現簡單,成本低

不保證最終一致

3、 柔性事務的實現方案

3.1、 兩階段提交(2PC

3.1.1、 原理

兩階段提交,基於XA協議,以及JTS協議JTA介面。

XA協議指的是TM(事務管理器)和RM(資源管理器)之間的介面Tuxedo提出。XA中大致分為兩部分:事務管理器和本地資源管理器。其中本地資源管理器往往由資料庫實現,比如OracleDB2這些商業資料庫都實現了XA介面,而事務管理器作為全域性的排程者,負責各個本地資源的提交和回滾。XA實現分散式事務的原理如下:

正常情況

異常情況

JavaEE平臺下,WebLogicWebshare等主流商用的應用伺服器提供了JTA的實現和支援。而在Tomcat下是沒有實現的,但是可以藉助第三方的框架JotmAutomikos等來實現,兩者均支援spring事務整合

3.1.2、 缺點

缺陷

兩階段提交中的第二階段, 協調者需要等待所有參與者發出yes請求, 或者一個參與者發出no請求後, 才能執行提交或者中斷操作. 這會造成長時間同時鎖住多個資源, 造成效能瓶頸, 如果參與者有一個耗時長的操作, 效能損耗會更明顯.

實現複雜, 不利於系統的擴充套件, 不推薦.

現在幾乎很少使用

3.2、 TCCTry-Confirm-cancle

3.2.1、 原理

TCC是基於業務層面的事務定義。鎖粒度完全由業務自己控制。它本質是一種補償的思路。它把事務執行過程分成 TryConfirm / Cancel 兩個階段。在每個階段的邏輯由業務程式碼控制。這樣就事務的鎖粒度可以完全自由控制。業務可以在犧牲隔離性的情況下,獲取更高的效能。

l Try 階段

n Try :嘗試執行業務

完成所有業務檢查( 一致性 )

預留必須業務資源( 準隔離性 )

l Confirm / Cancel 階段:

n Confirm :確認執行業務

u 真正執行業務

u 不做任務業務檢查

u Confirm 操作滿足冪等性

n Cancel :取消執行業務

釋放 Try 階段預留的業務資源

u Cancel 操作滿足冪等性

u Confirm Cancel 互斥

原理圖

3.2.2、 例項

在電商網站中一個經典的案例是這樣的使用者下單基於訂單系統實現操作訂單表;同時下單需要對商品進行減庫存操作,在庫存系統完成;同時還要對使用者進行積分獎勵,在使用者中心完成。這樣就出現了分散式事務。

我們用這個業務場景來解釋TCC的過程

l try:嘗試執行業務

完成業務檢查預留必須業務資源

在本例中判斷庫存是否充足如果充足鎖定庫存資料

l confirm/cancel:

n Confirm

確認執行業務,利用try階段預留的資源進行操作,如果失敗還要重試,因此要保證介面的冪等性

在本例中我們在庫存系統減庫存同時在使用者中心給使用者增加積分

n Cancel

如果confirm階段出現異常、超時。則呼叫cancel取消執行業務,進行事務補償(例如逆向操作)。釋放try階段鎖定的資源。如果在事務補償過程中出現異常,也必須進行重試。如果超過重試次數後,依然無法成功,則記錄日誌,以便後續人工介入進行事務補償操作。

u 在本例中,我們嘗試恢復庫存。同時取消使用者積分。

3.2.3、 優缺點

優點

l TCCtry、confirm等操作全部有使用者定義因此鎖定粒度由使用者自由控制各個資源獨立鎖定分別提交釋放,無需等待對方。失敗後是執行cancel中的補償型操作即可。

事務執行效率高時間短

能夠保證嚴格的資料一致性

缺點

正是因為需要使用者編寫所有的tryconfirmcancel操作,另外還有重試、冪等的要求,日誌的記錄等,實現複雜度較高,開發成本增加。

目前有一些開源的TCC框架

3.2.4、 使用場景

對一致性要求較高事務時效性比較敏感的業務

3.3、 非同步確保

這種實現方式的思路,其實是源於ebay,後來通過支付寶等公司的佈道,在業內廣泛使用。其基本的設計思想是將遠端分散式事務拆分成一系列的本地事務。如果不考慮效能及設計優雅,藉助關係型資料庫中的表即可實現。

在這個實現中將分佈事事務拆分成了主動方事務和被動方事務通過mq進行非同步通知來確保最終的資料一致性。

優點

tcc相比,實現方式較為簡單,開發成本低。

缺點

l 資料一致性完全依賴於訊息服務,因此訊息服務必須是可靠的。

需要處理被動業務方的冪等問題

被動業務失敗不會導致主動業務的回滾

業務與訊息服務耦合

3.3.1、 業務與訊息耦合:

3.3.2、 業務與訊息的分離

剛才的實現中,業務方在進行業務處理的同時,還需要對訊息資料進行持久化,程式碼耦合,不方便以後的維護。

我們可以採用下面的模式將訊息與業務解耦

優點:

訊息系統與業務系統解耦

訊息系統可以獨立儲存獨立伸縮

缺點

l 每次訊息傳送,需要兩次請求

業務處理系統需要提供業務狀態查詢介面

3.3.3、 使用場景

對事務一致性的時效要求不高的業務例如跨行轉賬支付寶餘額寶轉賬

3.4、 最大努力通知

3.4.1、 原理

最大努力通知主要用於對於事務的一致性不是特別敏感的事務,實現事務的弱一致性。可以通過訊息中介軟體實現。與前面非同步確保型操作不同的一點是, 在訊息由MQ Server投遞到消費者之後, 允許在達到最大重試次數之後正常結束事務.

主業務完成後,通過mq通知被動業務(允許訊息丟失)

通知失敗後主動方 按照一定的時間階梯進行訊息傳送重試直到超過最大重試次數為止

主動方提供業務查詢介面以便被動方後續進行通知失敗後的補償恢復丟失訊息

3.4.2、 實現

實現