天天看點

聊聊微服務架構及分布式事務解決方案!

分布式事務場景如何設計系統架構及解決資料一緻性問題,個人了解最終方案把握以下原則就可以了,那就是:大事務=小事務(原子事務)+異步(消息通知),解決分布式事務的最好辦法其實就是不考慮分布式事務,将一個大的業務進行拆分,整個大的業務流程,轉化成若幹個小的業務流程,然後通過設計補償流程進而考慮最終一緻性。

什麼是事務

事務(Transaction)及其ACID屬性

事務是由一組SQL語句組成的邏輯處理單元,事務具有以下4個屬性,通常簡稱為事務的ACID屬性:

原子性(Atomicity):事務是一個原子操作單元,其對資料的修改,要麼全都執行,要麼全都不執行。

一緻性(Consistent):在事務開始和完成時,資料都必須保持一緻狀态。這意味着所有相關的資料規則都必須應用于事務的修改,以保持資料的完整性;事務結束時,所有的内部資料結構(如B樹索引或雙向連結清單)也都必須是正确的。

隔離性(Isoation):資料庫系統提供一定的隔離機制,保證事務在不受外部并發操作影響的“獨立”環境執行。這意味着事務處理過程中的中間狀态對外部是不可見的,反之亦然。

持久性(Durabe):事務完成之後,它對于資料的修改是永久性的,即使出現系統故障也能夠保持。

典型場景:銀行轉賬業務

例如:李雷賬戶中有500塊錢,韓梅梅賬戶有200塊錢,李雷要從自己的賬戶中轉100塊錢給韓梅梅,轉賬(事務)成功執行完成後應該是李雷賬戶減100變為400,韓梅梅賬戶加100變為300,不能出現其他情況,即在事務開始和結束時資料都必須保持一緻狀态(一緻性),事務結束時所有的資料及結構都必須是正确的。并且同樣的轉賬操作(同一流水,即一次轉賬操作)無論執行多少次結果都相同(幂等性)。幂等性可以點選這裡參考這篇文章。

電商場景:流量充值業務

再說我們做的一個項目:中國移動-流量充值能力中心,核心業務流程為:

使用者進入流量充值商品購買頁面,選擇流量商品;

購買流量充值商品,有庫存限制則判斷庫存,生成流量購買訂單;

選擇對應的支付方式(和包、銀聯、支付寶、微信)進行支付操作;

支付成功後,近實時流量到賬即可使用流量商品;

此業務流程看似不是很複雜對吧,不涉及到類似電商業務的實物購買,但是我認為其中的差別并不是很大,隻是缺少電商中的物流發貨流程,其他流程幾乎是一樣的,也有庫存以及優惠折扣等業務存在。

整個系統互動如下圖:

聊聊微服務架構及分布式事務解決方案!

分布式事務

上述兩個場景的業務需求已經說完了,接着談談分布式事務,要說分布式事務那就先聊聊本地事務與分布式事務:

Ps:**相同點:**首先都是要保證資料正确(即ACID),本地事務與分布式事務還可以對應為:剛性事務與柔性事務,在我個人了解剛性事務與柔性事務的最大差別就是:一個完整的事務操作是否可以在同一實體媒體(例如:記憶體)上同時完成;柔性事務就是一個完整事務需要跨實體媒體或跨實體節點(網絡通訊),那麼排它鎖、共享鎖等等就沒有用武之地了(這裡并不是指大事務拆小事務【本地事務】後),無法保證原子性(Atomicity)完成事務。個人了解分布式(柔性)事務本質意義上就是-僞事務,柔性事務其實就是根據不同的業務場景使用不同的方法實作最終一緻性,因為可以根據業務的特性做部分取舍,在業務過程中可以容忍一定時間内的資料不一緻。

在知乎上面看過一篇文章,支付寶的柔性事務實作方式有四種分别針對不同的業務場景,如下圖:

聊聊微服務架構及分布式事務解決方案!

兩階段型

補償型

異步確定型

最大努力通知型

回到我們流量交易中心的業務場景。通過Dubbo實作了微服務化,大緻拆分如下:

商品服務

訂單服務

庫存服務

支付服務

直充服務

消息服務

等其他服務

場景一:

庫存數量與訂單數量一緻性,采用補償型+最大努力通知型,采用原因為不涉及跨機房和長事務(正常情況下庫存與訂單服務處理很快):

使用者下單先減庫存,庫存減成功後;

調用下單服務:

2-1.下單成功,兩事務均送出完成;

2-2.下單失敗,庫存復原,兩事務均失敗,此處還有一個保障機制(最大努力通知型),就是如果調用庫存服務異常,确定庫存復原失敗了,則放入消息服務(延時消息隊列)分階段定時重試,努力重試保證庫存服務正常後成功復原。消息隊列選型可以點選這裡參考這篇文章。

場景二:

訂單資訊、支付資訊、充值資訊三者之間的一緻性,采用異步確定型的原因是,整個業務鍊路太長且跨不同的機房系統,網絡延遲較高,業務方面恰好不需要非常高的實時性,是以采用小事務+異步通知,目前正常情況下使用者從下單到完成支付到流量到賬平均為1-5分鐘左右:

下單成功即訂單服務建立訂單成功并發送支付請求到支付網關系統(訂單狀态-待支付,超過1小時未支付則流轉為逾時未付撤銷,此處用到了RocketMQ的延時消費恰好實作定時器業務場景)。

傳回支付頁面,使用者在支付交易系統完成支付業務流程,支付網關異步通知流量中心,流量中心接收到支付成功狀态後修改訂單狀态-支付成功,并給支付網關傳回成功結果(此處并發壓力目前不大,暫時沒有再進行異步解耦)。

流量中心修改完訂單狀态後,調用消息服務将直充業務放入消息隊列,對直充業務進行解耦(原因是直充需要調用31省移動CRM系統,此鍊路過長,且部分省CRM系統耗時非常大,每個省的處理能力不同,經常出現20秒以上的逾時,是以要考慮部分逾時較高的省份拖垮系統,進行業務的削峰填谷);

3-1. 當直充成功時,修改訂單狀态-已完成;

3-2.當直充失敗時(移動特性,例如:直充時正好使用者銷戶或者停機了),修改訂單狀态為待退款,并調用支付網關系統的退款接口,退款成功後支付網關異步通知流量中心,流量中心修改訂單狀态為-退款成功;

3-3.當直充逾時時,調用定時任務服務進行逾時重試機制(第一次重試在10分鐘後執行、第二次在30分鐘後、第三次…..),直到最大逾時重試次數後還得不到直充結果,訂單狀态會卡在支付成功狀态,依賴T+1對賬稽核流程保證最終一緻性,訂單狀态根據對賬結果流轉為:已完成或待退款–>退款成功。

場景三:

直充到賬後的消息通知(APP消息推送或短信通知),采用最大努力通知型,這個業務場景比較簡單,在直充成功後,訂單狀态流轉為已完成,此時通過消息服務進行到賬通知業務的解耦,調用消息服務失敗的情況下,使用定時任務努力通知。

場景四:

對賬稽核:

按照支付賬期每日進行T+1對賬,對賬原則:以支付交易記錄為準,對流量中心訂單記錄+支付網關交易記錄+省CRM充值記錄三方比對,将某些中間狀态的訂單(例如:支付成功、待退款)核對後将訂單狀态流轉完結(已完成、退款成功)。

結算稽核:

對賬成功後的資料定期進入結算流程,對支付網關周期内的支付金額與結算資料的金額進行核對,稽核成功後進行财務結算流程,将錢結算給省公司,并提供結算明細給省公司,供省公司與直充成本記錄進行複核。

Ps:以下是流量中心的部分架構設計,總體原則方向:微服務化

流量中心-架構設計

聊聊微服務架構及分布式事務解決方案!

架構設計思想:在系統初期設計時以及部分硬性環境限制下,我們根據業務拆分為多個子系統(微服務):商品服務、訂單服務、庫存服務、支付網關、統一接口平台、對賬服務、結算服務、網關對接服務等,後續還會增加:賬戶服務、虛拟貨币服務、卡券服務等等…。

按照微服務的核心設計思想,所有服務完全獨立、隔離,是以所有服務從上至下:請求接入(連接配接管理)、請求處理(計算服務)、資料存儲(存儲服務)進行拆分,接入與計算盡最大可能實作無狀态,資料存儲進行垂直+水準拆分,垂直拆分:商品庫-mysql(讀多寫少,主從架構+讀寫分離)+redis(讀多寫少,叢集方式)、訂單庫-mysql(讀寫均衡,多主多從+水準拆分)、庫存專用庫-redis(分布式+主備容災)、外部交易系統-支付網關、外部辦理系統-統一接口平台。

Ps:此架構目前已支撐總交易額3.6億,總訂單4680萬,日均交易額500萬,日訂單量50萬,後續業務量持續增加的情況下按照微服務思想繼續拆分,例如将訂單服務再拆分為:下單服務、查單服務,直到根據業務需求與系統關系耦合性拆分到最細粒度為止。

性能擴充:應用層計算服務(無狀态應用)通過增加服務節點同比提升運算性能,配套品質(性能)監控服務dubbo monitor及整合Netflix的Hystrix熔斷器對業務品質進行管理實作應用層的動态擴縮容。

容量擴充:資料層存儲服務(有狀态應用)通過對資料水準拆分實作容量的無限擴容,Nosql類方案:Codis中間件;關系型資料庫:Mycat資料庫分庫分表中間件。目前項目中采用twitter的snowflake唯一ID生成器(根據業務場景優化後)自己實作資料的水準拆分和路由規則。

存儲性能:Nosql:針對讀多寫少場景-使用淘寶的Tedis(多寫随機讀的特性提高性能),讀寫均衡使用-Codis;Mysql:讀多寫少場景使用一主多從架構(例如商品資訊),讀寫均衡場景使用多主多從架構(例如訂單資訊)。

整體拆分原則如下圖:

聊聊微服務架構及分布式事務解決方案!

Never Give Up!