rocketmq事務消息入門介紹

引出分佈式事務相關內容面試

這裏主要是想說明下,是什麼背景下面產生了此類問題。redis

首先咱們來講說事務,說道事務,首先讓我想到的就是我大學的時候,老師常常舉例轉帳的事情,例子是這樣的:spring

銀行轉帳!張三轉100塊到李四的帳戶,這其實須要兩條SQL語句:
  • 給張三的帳戶減去100元
  • 給李四的帳戶加上100元
若是在第一條SQL語句執行成功後,在執行第二條SQL語句以前,程序被中斷了(多是拋出了某個異常,也多是其餘什麼緣由),那麼李四的帳戶沒有加上100元,而張三卻減去了100元。這確定是不行的!你如今可能已經知道什麼是事務了吧!事務中的多個操做,要麼徹底成功,要麼徹底失敗!不可能存在成功一半的狀況!也就是說給張三的帳戶減去100元若是成功了,那麼給李四的帳戶加上100元的操做也必須是成功的;不然給張三減去100元,以及給李四加上100元都是失敗的!

若是在單個服務裏面,咱們使用spring的話,咱們使用一個註解就解決了這個問題(@Transactional註解就解決了,基本上就沒有下文什麼事情了。)數據庫

隨着各各公司服務愈來愈複雜,數據量愈來愈多,慢慢的公司就引入了微服務以及分庫分表等技術,這些技術的確很是的有用,可是在解決事務方面帶來了一下問題。apache

強調下:分佈式事務,咱們通常都是強調的最終一致性,而不是強一致性!!!網絡

主要歸納爲3類:架構

  • 基於單個JVM,數據庫分庫分表了(跨多個數據庫)。
  • 基於多JVM,服務拆分了(不跨數據庫)。
  • 基於多JVM,服務拆分了 而且數據庫分庫分表了。

正是爲了解決上面的3類問題,才引入了分佈式事務相關的技術來解決這些問題。分佈式

Half(Prepare) Message微服務

指的是暫不能投遞的消息,發送方已經將消息成功發送到了 MQ 服務端,可是服務端未收到生產者對該消息的二次確認,此時該消息被標記成「暫不能投遞」狀態,處於該種狀態下的消息即半消息。學習

消息回查

因爲網絡閃斷、生產者應用重啓等緣由,致使某條事務消息的二次確認丟失,MQ 服務端經過掃描發現某條消息長期處於「半消息」時,須要主動向消息生產者詢問該消息的最終狀態(Commit 或是 Rollback),該過程即消息回查。

執行流程圖

 

 

 

 

 

  1. 發送方向 MQ 服務端發送消息。
  2. MQ Server 將消息持久化成功以後,向發送方 ACK 確認消息已經發送成功,此時消息爲半消息。
  3. 發送方開始執行本地事務邏輯。
  4. 發送方根據本地事務執行結果向 MQ Server 提交二次確認(Commit 或是 Rollback),MQ Server 收到 Commit 狀態則將半消息標記爲可投遞,訂閱方最終將收到該消息;MQ Server 收到 Rollback 狀態則刪除半消息,訂閱方將不會接受該消息。
  5. 在斷網或者是應用重啓的特殊狀況下,上述步驟4提交的二次確認最終未到達 MQ Server,通過固定時間後 MQ Server 將對該消息發起消息回查。
  6. 發送方收到消息回查後,須要檢查對應消息的本地事務執行的最終結果。
  7. 發送方根據檢查獲得的本地事務的最終狀態再次提交二次確認,MQ Server 仍按照步驟4對半消息進行操做。

事務消息發送對應步驟一、二、三、4,事務消息回查對應步驟五、六、7。

RocketMQ事務消息如何使用

一、引入 rocketmq-client

 

 

 

 

目前尚未,等幾天就會有了,或者本身下載源碼進行打包到本身的私有倉庫也是同樣的,通過和4.2.0的引入差很少,就是換成4.3.0便可。

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.3.0</version>
</dependency>

二、編寫Producer

 

 

 

 

備註:和普通消息發送 DefaultMQProducer有所不一樣,這裏使用的是 TransactionMQProducer

 

 

 

 

 

關鍵點: 本身實現TransactionListener接口,並實現 executeLocalTransaction方法(執行本地事務的,通常就是操做DB相關內容)和 checkLocalTransaction方法(用來提供給broker進行會查本地事務消息的,把本地事務執行的結果存儲到redis或者DB中均可以,爲會查作數據準備)。

仍是以:給張三的帳戶減去100元, 給李四的帳戶加上100元爲例。這個時候咱們發送就至關於作的是張三的帳戶減去100元的操做,而且操做DB成功了,下面就是另外對李四的帳戶加上100元的操做了,這個時候就是至關於定義剛剛發送事務消息的topic,消費端和咱們普通的消費端沒有什麼區別。

思考:假如這個時候咱們消費端失敗了怎麼辦呢?(這個問題後續有討論,消費失敗有2種,第一種是超時了,咱們重試便可,第二種是真的處理失敗了?該怎麼辦呢?)

RocketMQ事務消息是怎麼實現的

第一感受和定時消息作法很是相似,可是比定時消息要複雜。定時消息內容在:RocketMQ(九):消息發送(續)裏面提到過。

本質: 定時消息先把定時消息的topic修改成SCHEDULE_TOPIC_XXXX,以後一系列處理……,咱們這個事務消息也是同樣,先發送Half(Prepare) Message消息的時候,其實topic內容也繼續了修改(RMQ_SYS_TRANS_HALF_TOPIC),全部consumer是不可見的(若是提交就用真實topic,若是須要回滾那麼就那臨時的topic內容刪除便可。)

Half(Prepare) Message修改topic斷點以下:

 

 

 

 

本篇僅僅是一個入門介紹,裏面具體細節後續章節會進行分析。

思考: 若是把發送普通消息和本地執行邏輯放在一個事務裏面,若是執行事務成功就發送普通消息,若是失敗就回滾好像也是能夠,那麼這種事務消息相對其有什麼優點或者好處呢??? 思考下。

爲何須要事務消息會查機制

其實這個內容在,RocketMQ事務消息介紹裏面也說明了,因爲網絡閃斷、生產者應用重啓等緣由,致使某條事務消息的二次確認丟失,MQ 服務端經過掃描發現某條消息長期處於「半消息」時,須要主動向消息生產者詢問該消息的最終狀態(Commit 或是 Rollback),該過程即消息回查。那麼RocketMQ到底怎麼作的呢?下面立刻就會介紹。

RocketMQ是怎麼進行事務消息會查的

每60s會對Half(Prepare) Message的topic主題爲RMQ_SYS_TRANS_HALF_TOPIC的消息進行check。

 

 

 

 

 

 

 

 

broker會調用本身實現TransactionListener接口的checkLocalTransaction方法

 

 

 

 

備註: 就是RocketMQ已經實現這個機制,今天這篇僅僅是入門介紹,並無涉及到不少細節,先把大概流程說明白,後續再具體細節進行開篇說明。

RocketMQ對於分佈式事務解決還有那些侷限性?以及說明

在RocketMQ事務消息如何使用的時候咱們提到,若是消費失敗怎麼辦?消費失敗有2種,第一種是超時了,咱們重試便可,第二種是真的處理失敗了?仔細思考下,這塊仍是蠻複雜的,假如須要有7-8個業務模塊呢,其中執行到第6個業務模塊就失敗呢? 這種重試好幾回仍是失敗,咱們該如何處理呢???是回滾前面5個操做嗎?好複雜好複雜,爲何RocketMQ不提供自動回滾呢? 但願你們思考下,若是失敗率比較大,那麼就是系統問題須要優化代碼業務……

據零度瞭解,不少這塊是經過人工介入以及T+1對帳的以及補償機制等。

歡迎工做一到五年的Java工程師朋友們加入Java架構開發:點擊連接加入羣聊【Java架構交流羣】:https://jq.qq.com/?_wv=1027&k=5DmXtYD

本羣提供免費的學習指導 架構資料 以及免費的解答

不懂得問題均可以在本羣提出來 以後還會有職業生涯規劃以及面試指導

同時你們能夠多多關注一下小編 你們一塊兒學習進步

相關文章
相關標籤/搜索