RocketMQ事務消息學習及刨坑過程

1、背景

MQ組件是系統架構裏必不可少的一門利器,設計層面能夠下降系統耦合度,高併發場景又能夠起到削峯填谷的做用,從單體應用到集羣部署方案,再到如今的微服務架構,MQ憑藉其優秀的性能和高可靠性,獲得了普遍的承認。
隨着數據量增多,系統壓力變大,開始出現這種現象:數據庫已經更新了,但消息沒發出來,或者消息先發了,但後來數據庫更新失敗了,結果研發童鞋各類數據修復,這種生產問題出現的機率不大,但讓人很鬱悶。這個其實就是數據庫事務與MQ消息的一致性問題,簡單來說,數據庫的事務跟普通MQ消息發送沒法直接綁定與數據庫事務綁定在一塊兒,例如上面說起的兩種問題場景:數據庫

  1. 數據庫事務提交後發送MQ消息;
  2. MQ消息先發,而後再提交數據庫事務。

場景1的問題是數據庫事務可能剛剛提交,服務器就宕機了,MQ消息沒發出去,場景2的問題就是MQ消息發送出去了,但數據庫事務提交失敗,又沒辦法追加已經發出去的MQ消息,結果致使數據沒更新,下游已經收到消息,最終事務出現不一致的狀況。服務器

2、事務消息的引出

咱們以微服務架構的購物場景爲例,參照一下RocketMQ官方的例子,用戶A發起訂單,支付100塊錢操做完成後,能獲得100積分,帳戶服務和會員服務是兩個獨立的微服務模塊,有各自的數據庫,按照上文說起的問題可能性,將會出現這些狀況:網絡

  • 若是先扣款,再發消息,可能錢剛扣完,宕機了,消息沒發出去,結果積分沒增長。
  • 若是先發消息,再扣款,可能積分增長了,但錢沒扣掉,白送了100積分給人家。
  • 錢正常扣了,消息也發送成功了,但會員服務實例消費消息出現問題,結果積分沒增長。

RocketMQ事務消息學習及刨坑過程

由此引出的是數據庫事務與MQ消息的事務一致性問題,rocketmq事務消息解決的問題:解決本地事務執行與消息發送的原子性問題。這裏界限必定要明白,是確保MQ生產端正確無誤地將消息發送出來,沒有多發,也不會漏發。但至於發送後消費端有沒有正常的消費掉(如上面說起的第三種狀況,錢正常扣了,消息也發了,但下游消費出問題致使積分不對),這種異常場景將由MQ消息消費失敗重試機制來保證,不在這次的討論範圍內。架構

經常使用的MQ組件針對此場景都有本身的實現方案,如ActiveMQ使用AMQP協議(二階提交方式)保證消息正確發送,這裏咱們以RocketMQ爲重點進行學習。併發

3、RocketMQ事務消息設計思路

根據CAP理論,RocketMQ事務消息經過異步確保方式,保證事務的最終一致性。設計流程上借鑑兩階段提交理論,流程圖以下:異步

RocketMQ事務消息學習及刨坑過程

  1. 應用模塊遇到要發送事務消息的場景時,先發送prepare消息給MQ。
  2. prepare消息發送成功後,應用模塊執行數據庫事務(本地事務)。
  3. 根據數據庫事務執行的結果,再返回Commit或Rollback給MQ。
  4. 若是是Commit,MQ把消息下發給Consumer端,若是是Rollback,直接刪掉prepare消息。
  5. 第3步的執行結果若是沒響應,或是超時的,啓動定時任務回查事務狀態(最多重試15次,超過了默認丟棄此消息),處理結果同第4步。
  6. MQ消費的成功機制由MQ本身保證。

4、RocketMQ事務消息實現流程

以RocketMQ 4.5.2版本爲例,事務消息有專門的一個隊列RMQ_SYS_TRANS_HALF_TOPIC,全部的prepare消息都先往這裏放,當消息收到Commit請求後,就把消息再塞到真實的Topic隊列裏,供Consumer消費,同時向RMQ_SYS_TRANS_OP_HALF_TOPIC塞一條消息。簡易流程圖以下:ide

RocketMQ事務消息學習及刨坑過程

上述流程中,請容許我這樣劃分模塊職責:微服務

  1. RocketMQ Client即咱們工程中導入的依賴jar包,RocketMQ Broker端即部署的服務端,NameServer暫未體現。
  2. 應用模塊成對出現,上游爲事務消息生產端,下游爲事務消息消費端(事務消息對消費端是透明的,與普通消息一致)。

應用模塊的事務由於中斷,或是其餘的網絡緣由,致使沒法當即響應的,RocketMQ當作UNKNOW處理,RocketMQ事務消息還提供了一個補救方案:定時查詢事務消息的數據庫事務狀態高併發

簡易流程圖以下:性能

RocketMQ事務消息學習及刨坑過程

5、結束語

本篇簡單介紹了事務消息的解決的場景和職責的界限,基本的設計思路和流程,在此借鑑學習了RocketMQ做者的圖稿,而後挑了部分代碼做簡要的講解,仍是本身的刨坑過程,文章內有任何不正確或不詳盡之處請留言指導,謝謝。

相關文章
相關標籤/搜索