歡迎光臨
每天分享高質量文章

一個簡單的分佈式事務系統的實現(訂單系統)

點擊上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 

來源:http://t.cn/EhKG87r

       背景:公司最早的一個版本的訂單管理,是通過PHP+mysql的方案去實現的,這樣會有什麼問題呢,假設如果放到一個實體裡面,全部用一個單機事務去解決,這樣是能比較方便的解決資料一致性問題。但是存在兩個問題,一是無法進行多實體部署,用戶量增長以後,無法快速應對。二是,PHP中做事務,如果PHP遇到異常,有時並不會自動終止事務,導致DB被鎖住,這是第一個版本。之後,我們推出了第二個版本V2,這個版本的時候,我們已經開發好了,庫存管理系統,優惠券管理系統,PHP中,已經不直接通過DB去修改庫存和優惠券,而是通過接口訪問的方式去請求SERVER進行修改。這個版本,實際上已經從邏輯上,把訂單系統和庫存管理,優惠券管理系統已經獨立出來了。資料層面已經可以獨立部署,不再依賴一個單機事務去實現資料一致性功能了。但這個版本雖然解決了資料分佈的問題,但同時引入了一個新的問題,就是資料在訂單,庫存,優惠券之間無法保證一致性。舉個例子:下個訂單,呼叫庫存成功,鎖定優惠券失敗,生成訂單失敗。這時候就會導致優惠券資料不一致性情況出來,未下單的優惠券也被鎖住了。有同事可能會問:訂單如果創建失敗,那直接回滾優惠券操作,即去解鎖優惠券系統即可實現資料一致性。不錯,很多時候,是可以這麼操作,但如果你回滾的時候,失敗了呢?你是繼續在這等著直到成功,還是繼續等著?呵呵。。

       正是因為這樣,我們開發了V3版本,去解決這個問題。

       V3版本,我們把訂單系統的邏輯從PHP中抽離出來,為什麼儘量不在PHP裡面做這塊邏輯呢?主要有兩個考慮點:1、因為訂單服務這塊邏輯特別重要,是影響用戶操作的重要邏輯,且變動少,寫成一個SERVER相對容易保持穩定。2、PHP使用CI框架做事務的時候,如果事務中出現異常,可能導致事務不結束,一直死鎖的問題。

       訂單系統的邏輯架構大致如下:

         

        訂單系統中,統一通過接口呼叫,去訪問庫存管理,優惠券系統,通過mysql提供的事務機制去運算元據庫部分。這裡有一個前提條件,即是庫存管理與優惠券系統的接口均要實現可重入的特性(可參考上一篇文章“如何實現可重入接口”)。另外,還要引入一個差錯控制服務,用於做一些資料不一致的事後補嘗機制。差錯控制可以理解為一個訊息佇列機制,還有一個消費者服務從佇列中取出訊息進行消費。我們這裡採用阿裡雲的ONS服務做為訊息佇列,通過一個消費者去訂單訊息進行消費。

        生成訂單的邏輯如下:

        1、先把生成的訂單號發到差錯控制服務中。(這裡必須要有個延時處理的機制,延時給消費者消費訊息,因為要確保後面的流程有個結果,可以延時5分鐘以上)

        2、使用訂單號作為庫存單號去操作庫存管理系統。

        A)如果失敗,則使用相同訂單號去進行回滾請求操作。(這裡不論成功失敗,均傳回失敗,結束流程)

        B)如果成功,繼續往下執行。

        3、使用訂單號去鎖定優惠券系統。

        A)如果失敗,嘗試庫存回滾操作,嘗試執行解鎖操作。(這裡不論解鎖成功失敗,均傳回失敗,結束流程)

        B)如果成功,繼續往下執行。

        4、開啟事務,創建訂單相關資料。

        A)如果創建失敗,回滾事務,呼叫庫存回滾操作,呼叫優惠券解鎖操作。(不論呼叫成功與否,均傳回失敗,結束流程)

        B)如果創建成功,提交事務,傳回成功。

        大概流程如上所述。

        另外,差錯控制服務,這裡也大概描述一下其工作流程。

        1、去訂單庫中查看該訂單是否已經生成,如果已經生成,說明資料全部一致,無須做任何操作,直接消費此訊息。

        2、如果發現訂單未創建,則其中可能是其中某個環節失敗了。

        A)使用該訂單號去呼叫庫存回滾操作。如果失敗,結束流程,傳回稍後重新消費,等待訊息佇列重試推過來。

        B)如果成功,繼續往下執行,呼叫優惠券系統進行解瑣優惠券。如果失敗,則傳回稍後重新消費,等待訊息佇列重推訊息。如果成功,則消費此訊息。

        大致思路是通過一個差錯補嘗機制,非實時的自動進行資料一致性修複的方法,來保證絕大多數情況下的資料一致性。



如果你對 Dubbo / Netty 等等原始碼與原理感興趣,歡迎加入我的知識星球一起交流。長按下方二維碼噢

目前在知識星球更新了《Dubbo 原始碼解析》目錄如下:

01. 除錯環境搭建
02. 專案結構一覽
03. 配置 Configuration
04. 核心流程一覽

05. 拓展機制 SPI

06. 執行緒池

07. 服務暴露 Export

08. 服務取用 Refer

09. 註冊中心 Registry

10. 動態編譯 Compile

11. 動態代理 Proxy

12. 服務呼叫 Invoke

13. 呼叫特性 

14. 過濾器 Filter

15. NIO 服務器

16. P2P 服務器

17. HTTP 服務器

18. 序列化 Serialization

19. 集群容錯 Cluster

20. 優雅停機

21. 日誌適配

22. 狀態檢查

23. 監控中心 Monitor

24. 管理中心 Admin

25. 運維命令 QOS

26. 鏈路追蹤 Tracing

… 一共 69+ 篇

目前在知識星球更新了《Netty 原始碼解析》目錄如下:

01. 除錯環境搭建
02. NIO 基礎
03. Netty 簡介
04. 啟動 Bootstrap

05. 事件輪詢 EventLoop

06. 通道管道 ChannelPipeline

07. 通道 Channel

08. 位元組緩衝區 ByteBuf

09. 通道處理器 ChannelHandler

10. 編解碼 Codec

11. 工具類 Util

… 一共 61+ 篇

目前在知識星球更新了《資料庫物體設計》目錄如下:


01. 商品模塊
02. 交易模塊
03. 營銷模塊
04. 公用模塊

… 一共 17+ 篇

原始碼不易↓↓↓

點贊支持老艿艿↓↓

赞(0)

分享創造快樂