阿里業務研發經典案例:另類解法,分散式一致性
背景
在大型網際網路系統中,基於成本的考慮,普遍會使用MySQL 資料庫;同時由於業務量很大,通常會按照使用者維度對資料做垂直拆分,即大家常說的分庫分表。
在阿里巴巴的紅包系統中,紅包的發放操作會涉及兩個資料庫的事務操作,一個資料庫進行預算的扣減,另一個進行使用者紅包資料的寫入,那麼如何保證這兩個事務操作的一致性呢?
問題原因及分析
開發人員首先想到的就是使用MySQL 的XA 協議,它使用的是兩階段提交協議,如圖1所示。由事務協調者來保證所有的事務參與者都完成了第一階段的準備工作,如果所有參與者都準備好了,那麼就通知所有的參與者進行提交。MySQL 資料庫僅能扮演參與者的角色,協調者(事務管理器)需要由另外的應用擔任。
兩階段提交協議對於紅包系統來說,在XA 事務中的第一階段,預算端需要做的事情是凍結要扣除的預算,紅包資料端需要插入一條不可用的紅包資料。在XA 事務的第二階段,如果事務需要提交,那麼預算端需要將第一階段的凍結的預算轉化為實際的扣除,紅包資料端需要將剛才插入的那一條不可用的紅包資料變為可用;如果事務需要回滾,那麼預處端需要將第一階段的凍結的預算進行撤銷操作,紅包資料端需要刪除剛才插入的不可用的紅包資料。
對於任何一次不論是成功還是失敗的發放操作,預算端都會涉及兩次針對於預算紀錄的事務操作。眾所周知的是,該條記錄的操作會存在熱點寫的問題,使用XA 事務的方案會將熱點寫問題放大一倍。在業務場景中,使用XA 事務的方案看起來有些過於“悲觀”了,事實上紅包發放的成功與否幾乎完全取決於預算是否扣減成功。回到業務的根本需求上來,有以下兩個關鍵點。
(1)希望預算扣減成功與產生使用者紅包資料這兩件事要麼同時成功,要麼同時失敗,只要預算足夠,那麼理論上是肯定成功的。
(2)不可能將每一個發放操作變成一個一個順序的獨立事務,這樣不但效能非常差,同時後面的事務也並不關心預算的具體剩餘金額。所以實際上在發放操作中,很有可能看到一個是中間態的預算剩餘金額,這是允許的。
如果能存在一起機制,它能保證預算扣減成功後100%會通知到我們,這樣就可以利用這個機會去產生使用者紅包資料,如果產生失敗,那麼我們可以對已經扣減的預算進行一筆反向操作。
解決過程
最終的解決方案是開發人員設計了一個輕型的一致性訊息元件,把預算扣減成功等諸多業務操作事件寫入資料庫中,該訊息元件保證事件與業務操作處在同一個資料庫中,所以僅僅是一次簡單的本地事務操作。該訊息元件會對寫入的事件進行分發,通知每一個事件訂閱者(比如在當前的場景中就是進行使用者紅包資料寫入),然後對事件的處理結果進行記錄。
在一個成功的紅包發放操作中,對於預算端來說,進行了一次預算的扣減,一次事件寫入,可能會進行一次事件讀取,一次事件狀態更新;對於使用者紅包資料端,僅需要進行一次使用者紅包資料的寫入。可以看到,對於預算扣減的熱點資料操作,新的方案並沒有放大它。同時,失敗的紅包發放操作就更簡單了,僅僅是一次失敗的預算扣減,沒有事件,沒有使用者紅包端的任何操作。
另外,在實際使用中開發人員發現,使用這樣的一套方案還可以降低系統的編碼以及運維的複雜度,不再需要為預算端設計凍結操作以及使用者紅包資料端設計不可用資料,也不需要引入另外一套獨立的事務協調系統。
這套系統命名為MiniBus,即微型匯流排,如圖2所示。
它包括以下三部分。
(1)事件釋出者Publisher。由業務邏輯在業務事務中呼叫,將事件寫入到與業務相同的資料庫中。
(2)事件配置Metadata。管理事件的基本資訊,訂閱關係等。
(3)事件偵錯程式Scheduler。讀取待分發的事件,根據訂閱關係進行分發,呼叫相應的事件處理器,然後記錄事件分發的結果。
該方案並不僅僅解決了紅包發放操作中的事務一致性問題,事實上,只要業務上滿足如下的兩個要求,它都適用。
(1)短暫的中間狀態是可以接受的。
(2)要求最終一終性。
同時,還有如下4 個方面的優點。
(1)較XA 方案更易於編碼和理解,已有程式碼的改造成本很低。
(2)資料庫消耗增加較少。
(3)系統簡單,外部依賴少,易於維護。
(4)相容資料庫上的其他他SQL 優化。
小結
好的技術方案都是對於業務場景的深刻理解和權衡之後獲得的,雖然通用的方案是首選,但它並不是唯一的好的選擇。
以上內容節選自《逆流而上:阿里巴巴技術成長之路》,點此連結可在博文視點官網檢視此書。
想及時獲得更多精彩文章,可在微信中搜尋“博文視點”或者掃描下方二維碼並關注。
相關文章
- 光碟機護理2.0 另類破解法 (857字)
- JavaScript經典案例(二)JavaScript
- MySQL經典案例分析MySql
- 分散式系統的經典基礎理論分散式
- 分散式事務最終一致性的簡單案例分散式
- 智慧垃圾分類回收系統解決方案(經典案例)
- Java基礎經典案例Java
- 阿里面試經歷及總結(資料研發、Java研發方向)阿里面試Java
- 分散式系列第一彈:分散式一致性!分散式
- C++ 經典案例1例C++
- OpenCV之C++經典案例OpenCVC++
- 記憶體補丁小小節---有聲有色另類解法 (3千字)記憶體
- 一道經典面試邏輯題的python解法面試Python
- 嵌入式開發 ARM入門經典
- [分散式]高併發案例---庫存超發問題分散式
- Python入門經典案例一Python
- Linux 【Shell指令碼經典案例】Linux指令碼
- 第八篇:經典案例 - 排序排序
- oracle約束學習經典案例Oracle
- 分散式計算技術(上):經典計算框架MapReduce、Spark 解析分散式框架Spark
- Java多執行緒之併發安全經典案例-賣票Java執行緒
- javascript 經典函式 (轉)JavaScript函式
- 深入理解負載均衡經典案例負載
- Jdon Jpetstore經典應用案例釋出
- 分散式系統:一致性模型分散式模型
- 曾經遇到的一個另類的排序問題.排序
- 對話巨杉核心研發團隊:分散式資料庫自研之路分散式資料庫
- java分散式(類特性)Java分散式
- Redis分散式鎖加鎖案例Redis分散式
- 分散式事務(2)---強一致性分散式事務解決方案分散式
- Paxos——分散式一致性演算法分散式演算法
- paxos分散式一致性演算法分散式演算法
- 深入剖析分散式事務一致性分散式
- 分散式系統一致性協議分散式協議
- 分散式一致性演算法Paxos分散式演算法
- JavaScript經典案例:鍵盤控制元素移動JavaScript
- 另類SQL拼接方法SQL
- 另類SQL優化SQL優化