1. 程式人生 > >微服務架構及分布式事務解決方案

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

路由 ons city nic net 原則 分享圖片 成功 ket

分布式事務

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

What’s 事務

事務(Transaction)及其ACID屬性

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

  1. 原子性(Atomicity):事務是一個原子操作單元,其對數據的修改,要麽全都執行,要麽全都不執行。
  2. 一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態。這意味著所有相關的數據規則都必須應用於事務的修改,以保持數據的完整性;事務結束時,所有的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。
  3. 隔離性(Isoation):數據庫系統提供一定的隔離機制,保證事務在不受外部並發操作影響的“獨立”環境執行。這意味著事務處理過程中的中間狀態對外部是不可見的,反之亦然。
  4. 持久性(Durabe):事務完成之後,它對於數據的修改是永久性的,即使出現系統故障也能夠保持。

典型場景:銀行轉賬業務

例如:李雷賬戶中有500塊錢,韓梅梅賬戶有200塊錢,李雷要從自己的賬戶中轉100塊錢給韓梅梅,轉賬(事務)成功執行完成後應該是李雷賬戶減100變為400,韓梅梅賬戶加100變為300,不能出現其他情況,即在事務開始和結束時數據都必須保持一致狀態(一致性),事務結束時所有的數據及結構都必須是正確的。並且同樣的轉賬操作(同一流水,即一次轉賬操作)無論執行多少次結果都相同(冪等性)。

電商場景:流量充值業務

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

  1. 用戶進入流量充值商品購買頁面,選擇流量商品;
  2. 購買流量充值商品,有庫存限制則判斷庫存,生成流量購買訂單;
  3. 選擇對應的支付方式(和包、銀聯、支付寶、微信)進行支付操作;
  4. 支付成功後,近實時流量到賬即可使用流量商品;

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

整個系統交互如下圖:

技術分享圖片

分布式事務

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

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

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

技術分享圖片

  1. 兩階段型
  2. 補償型
  3. 異步確保型
  4. 最大努力通知型

回到我們流量交易中心的業務場景:

通過Dubbo實現了微服務化,大致拆分如下:

  1. 商品服務
  2. 訂單服務
  3. 庫存服務
  4. 支付服務
  5. 直充服務
  6. 消息服務
  7. 等其他服務

場景一:

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

  1. 用戶下單先減庫存,庫存減成功後;
  2. 調用下單服務:
  3. 2-1. 下單成功,兩事務均提交完成;
  4. 2-2. 下單失敗,庫存回滾,兩事務均失敗,此處還有一個保障機制(最大努力通知型),就是如果調用庫存服務異常,確定庫存回滾失敗了,則放入消息服務(延時消息隊列)分階段定時重試,努力重試保證庫存服務正常後成功回滾。

場景二:

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

  1. 下單成功即訂單服務創建訂單成功並發送支付請求到支付網關系統(訂單狀態-待支付,超過1小時未支付則流轉為超時未付撤銷,此處用到了RocketMQ的延時消費恰好實現定時器業務場景)。
  2. 返回支付頁面,用戶在支付交易系統完成支付業務流程,支付網關異步通知流量中心,流量中心接收到支付成功狀態後修改訂單狀態-支付成功,並給支付網關返回成功結果(此處並發壓力目前不大,暫時沒有再進行異步解耦)。
  3. 流量中心修改完訂單狀態後,調用消息服務將直充業務放入消息隊列,對直充業務進行解耦(原因是直充需要調用31省移動CRM系統,此鏈路過長,且部分省CRM系統耗時非常大,每個省的處理能力不同,經常出現20秒以上的超時,因此要考慮部分超時較高的省份拖垮系統,進行業務的削峰填谷);
  4. 3-1. 當直充成功時,修改訂單狀態-已完成;
  5. 3-2. 當直充失敗時(移動特性,例如:直充時正好用戶銷戶或者停機了),修改訂單狀態為待退款,並調用支付網關系統的退款接口,退款成功後支付網關異步通知流量中心,流量中心修改訂單狀態為-退款成功;
  6. 3-3. 當直充超時時,調用定時任務服務進行超時重試機制(第一次重試在10分鐘後執行、第二次在30分鐘後、第三次…..),直到最大超時重試次數後還得不到直充結果,訂單狀態會卡在支付成功狀態,依賴T+1對賬稽核流程保證最終一致性,訂單狀態根據對賬結果流轉為:已完成或待退款–>退款成功。

場景三:

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

場景四:

對賬稽核:

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

結算稽核:

對賬成功後的數據定期進入結算流程,對支付網關周期內的支付金額與結算數據的金額進行核對,稽核成功後進行財務結算流程,將錢結算給省公司,並提供結算明細給省公司,供省公司與直充成本記錄進行復核。

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

流量中心-架構設計

技術分享圖片

架構設計思想:在系統初期設計時以及部分硬性環境約束下,我們根據業務拆分為多個子系統(微服務):商品服務、訂單服務、庫存服務、支付網關、統一接口平臺、對賬服務、結算服務、網關對接服務等,後續還會增加:賬戶服務、虛擬貨幣服務、卡券服務等等…。按照微服務的核心設計思想,所有服務完全獨立、隔離,因此所有服務從上至下:請求接入(連接管理)、請求處理(計算服務)、數據存儲(存儲服務)進行拆分,接入與計算盡最大可能實現無狀態,數據存儲進行垂直+水平拆分,垂直拆分:商品庫-mysql(讀多寫少,主從架構+讀寫分離)+redis(讀多寫少,集群方式)、訂單庫-mysql(讀寫均衡,多主多從+水平拆分)、庫存專用庫-redis(分布式+主備容災)、外部交易系統-支付網關、外部辦理系統-統一接口平臺。

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

  1. 性能擴展:應用層計算服務(無狀態應用)通過增加服務節點同比提升運算性能,配套質量(性能)監控服務dubbo monitor及整合Netflix的Hystrix熔斷器對業務質量進行管理實現應用層的動態擴縮容。
  2. 容量擴展:數據層存儲服務(有狀態應用)通過對數據水平拆分實現容量的無限擴容,Nosql類方案:Codis中間件;關系型數據庫:Mycat數據庫分庫分表中間件。目前項目中采用twitter的snowflake唯一ID生成器(根據業務場景優化後)自己實現數據的水平拆分和路由規則。
  3. 存儲性能:Nosql:針對讀多寫少場景-使用淘寶的Tedis(多寫隨機讀的特性提高性能),讀寫均衡使用-Codis;Mysql:讀多寫少場景使用一主多從架構(例如商品信息),讀寫均衡場景使用多主多從架構(例如訂單信息)。

整體拆分原則如下圖:

技術分享圖片

來源:nickid.cn

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