1. 程式人生 > >微服務架構下的資料一致性保證(一)

微服務架構下的資料一致性保證(一)

大家好,今天我給大家分享的題目是微服務架構下的資料一致性保證。

blob.png

今天分享第一篇,主要內容包括:

1.傳統使用本地事務和分散式事務保證一致性。

2.傳統分散式事務不是微服務中一致性的最佳選擇。

3.微服務架構中應滿足資料最終一致性原則。

4.微服務架構實現最終一致性的三種模式。

5.對賬是最後的終極防線。

一、傳統使用本地事務和分散式事務保證一致性

傳統單機應用一般都會使用一個關係型資料庫,好處是應用可以使用 ACID transactions。為保證一致性我們只需要:開始一個事務,改變(插入,刪除,更新)很多行,然後提交事務(如果有異常時回滾事務)。更進一步,藉助開發平臺中的資料訪問技術和框架(如Spring),我們需要做的事情更少,只需要關注資料本身的改變。

隨著組織規模不斷擴大,業務量不斷增長,單機應用和資料庫已經不足以支援龐大的業務量和資料量,這個時候需要對應用和資料庫進行拆分,就出現了一個應用需要同時訪問兩個或兩個以上的資料庫情況。開始我們用分散式事務來保證一致性,也就是我們常說的兩階段提交協議(2PC)。

本地事務和分散式事務現在已經非常成熟,相關介紹很豐富,此處不多作討論。

二、傳統分散式事務不是微服務中一致性的最佳選擇

首先,對於微服務架構來說,資料訪問變得更加複雜,這是因為資料都是微服務私有的,唯一可訪問的方式就是通過API。這種打包資料訪問方式使得微服務之間鬆耦合,並且彼此之間獨立非常容易進行效能擴充套件。

其次,不同的微服務經常使用不同的資料庫。應用會產生各種不同型別的資料,關係型資料庫並不一定是最佳選擇。

例如,某個產生和查詢字串的應用採用Elasticsearch的字元搜尋引擎;某個產生社交圖片資料的應用可以採用圖資料庫,例如,Neo4j;

基於微服務的應用一般都使用SQL和NoSQL結合的模式。但是這些非關係型資料大多數並不支援2PC。

可見在微服務架構中已經不能選擇分散式事務了。

三、微服務架構中應滿足資料最終一致性原則

依據CAP理論,必須在可用性(availability)和一致性(consistency)之間做出選擇。如果選擇提供一致性需要付出在滿足一致性之前阻塞其他併發訪問的代價。這可能持續一個不確定的時間,尤其是在系統已經表現出高延遲時或者網路故障導致失去連線時。

依據目前的成功經驗,可用性一般是更好的選擇,但是在服務和資料庫之間維護資料一致性是非常根本的需求,微服務架構中選擇滿足最終一致性。

當然選擇了最終一致性,就要保證到最終的這段時間要在使用者可接受的範圍之內。

那麼我們怎麼實現最終一致性呢?

四、微服務架構實現最終一致性的三種模式

從一致性的本質來看,是要保證在一個業務邏輯中包含的服務要麼都成功,要麼都失敗。那我們怎麼選擇方向呢?保證成功還是保證失敗呢?

我們說業務模式決定了我們的選擇。實現最終一致性有三種模式:可靠事件模式、業務補償模式、TCC模式。

1) 可靠事件模式

可靠事件模式屬於事件驅動架構,當某件重要事情發生時,例如更新一個業務實體,微服務會向訊息代理髮佈一個事件。訊息代理會向訂閱事件的微服務推送事件,當訂閱這些事件的微服務接收此事件時,就可以完成自己的業務,也可能會引發更多的事件釋出。

1. 如訂單服務建立一個待支付的訂單,釋出一個“建立訂單”的事件。

2.支付服務消費“建立訂單”事件,支付完成後釋出一個“支付完成”事件。

3.訂單服務消費“支付完成”事件,訂單狀態更新為待出庫。

從而就實現了完成的業務流程。

這個過程可能導致出現不一致的地方在於:某個微服務在更新了業務實體後釋出事件卻失敗;雖然微服務釋出事件成功,但是訊息代理未能正確推送事件到訂閱的微服務;接受事件的微服務重複消費了事件。

可靠事件模式在於保證可靠事件投遞避免重複消費,可靠事件投遞定義為(a)每個服務原子性的業務操作和釋出事件(b)訊息代理確保事件傳遞至少一次。

避免重複消費要求服務實現冪等性,如支付服務不能因為重複收到事件而多次支付。

2) 補償模式

為了描述方便,這裡先定義兩個概念:

業務異常:業務邏輯產生錯誤的情況,比如賬戶餘額不足、商品庫存不足等。

技術異常:非業務邏輯產生的異常,如網路連線異常、網路超時等。

補償模式使用一個額外的協調服務來協調各個需要保證一致性的微服務,協調服務按順序呼叫各個微服務,如果某個微服務呼叫異常(包括業務異常和技術異常)就取消之前所有已經呼叫成功的微服務。

補償模式建議僅用於不能避免出現業務異常的情況,如果有可能應該優化業務模式,以避免要求補償事務。如賬戶餘額不足的業務異常可通過預先凍結金額的方式避免,商品庫存不足可要求商家準備額外的庫存等。

我們通過一個例項來說明補償模式,一家旅行公司提供預訂行程的業務,可以通過公司的網站提前預訂飛機票、火車票、酒店等。

假設一位客戶規劃的行程是,(1)上海-北京6月19日9點的某某航班,(2)某某酒店住宿3晚,(3)北京-上海6月22日17點火車。在客戶提交行程後,旅行公司的預訂行程業務按順序序列的呼叫航班預訂服務、酒店預訂服務、火車預訂服務。最後的火車預訂服務成功後整個預訂業務才算完成。

如果火車票預訂服務沒有呼叫成功,那麼之前預訂的航班、酒店都得取消。取消之前預訂的酒店、航班即為補償過程。

需要注意的是酒店的取消預訂、航班的取消預訂同樣不能保證一定成功,所以補償過程往往也同樣需要實現最終一致性,需要保證取消服務至少被呼叫一次和取消服務必須實現冪等性。

我們應該儘可能通過設計避免採用補償方式,比如上面的例子中,在預訂火車票失敗的時候可以提示客戶更改其他的時間。

 3) TCC模式(Try-Confirm-Cancel)

一個完整的TCC業務由一個主業務服務和若干個從業務服務組成,主業務服務發起並完成整個業務活動,TCC模式要求從服務提供三個介面:Try、Confirm、Cancel。

1) Try:完成所有業務檢查

預留必須業務資源

2) Confirm:真正執行業務

不作任何業務檢查

只使用Try階段預留的業務資源

Confirm操作滿足冪等性

3) Cancel:

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

Cancel操作滿足冪等性

整個TCC業務分成兩個階段完成。

第一階段:主業務服務分別呼叫所有從業務的try操作,並在活動管理器中登記所有從業務服務。當所有從業務服務的try操作都呼叫成功或者某個從業務服務的try操作失敗,進入第二階段。

第二階段:活動管理器根據第一階段的執行結果來執行confirm或cancel操作。如果第一階段所有try操作都成功,則活動管理器呼叫所有從業務活動的confirm操作。否則呼叫所有從業務服務的cancel操作。

需要注意的是第二階段confirm或cancel操作本身也是滿足最終一致性的過程,在呼叫confirm或cancel的時候也可能因為某種原因(比如網路)導致呼叫失敗,所以需要活動管理支援重試的能力,同時這也就要求confirm和cancel操作具有冪等性。