rocketmq 事務消息是如何保證發送消息不丟失的

前言

    rocketmq 消息隊列在大部分業務系統中都會用到(如下圖),服務A和服務B系統通過mq進行業務解耦;服務A處理完業務之後,發一條消息到rocketmq,服務B從rocketmq拉去消息進行消費。

 上面這個流程會有下面幾個問題:   

 1.如果服務A寫數據庫成功了,還沒來得及發送消息就宕機了,這就會導致服務B永遠消費不了消息,出現了數據不一致問題;

 2. 服務A寫數據庫成功,發送mq消息失敗,也會出現服務B消費不了消息的情況;

3.服務A寫數據庫成功,發mq消息成功了,但是服務A事務由於異常回滾了,服務B消費了消息。

 針對上面的幾個問題, 我們在生產開發中如何解決呢?

 

1.重試+回滾

針對第二個問題,我們可以使用重試加回滾的方式解決;先寫本地事務,然後發送mq消息,如果發送失敗再重試幾次,重試也是失敗就回滾本地事務。

 public  void doService() {
        //執行本地事務
        server.doLocalTransaction();

        for (int i = 0; i < 3 ; i++) {
            try {
                producer.send(message);
                return;
            } catch (Exception e) {
                continue;//繼續重試
            }
        }
          server.rollback();
    }

 缺點:本地事務和發送消息不在一個事務裏,如果mq重試也失敗後系統宕機了,服務A事務還是無法回滾。

2.事務+重試回滾

針對上面服務A事務無法回滾的問題,我們可以將發送消息流程加到整個事務裏來,出現異常事務會自動回滾。

@Transactional
        public  void doService() {
        //執行本地事務
        server.doLocalTransaction();


        for (int i = 0; i < 3 ; i++) {
            try {
                producer.send(message);
                return;
            } catch (Exception e) {
                continue;//繼續重試
            }
        }
         throw  new BusinessException("rollback....");
    }

 

缺點:如果出現網絡異常再重試發送消息,會導致數據資源被鎖定很長時間,影響數據庫的併發性能,同時也響應系統的性能。

3.補償機制

     服務A發送消息失敗什麼也不處理,j可以將數據狀態更改爲發送消息失敗,補償任務每五分鐘掃描一次數據庫,發現有發送消息失敗的數據則重新發送mq消息,將數據狀態更改爲成功。

 public  void doService() {
        //執行本地事務
        server.doLocalTransaction();
            try {
                producer.send(message);
                return;
            } catch (Exception e) {
                server.updateFail()
            }
          server.rollback();
    }

  ScheduledThreadPoolExecutor executor=new ScheduledThreadPoolExecutor();
       executor.scheduleAtFixedRate(()-> server.checkLocalTransaction(),0L,5, TimeUnit.MINUTES);

缺點:這個方案有點依賴數據庫做狀態判斷。

4.rocketmq 事務消息

使用rocketmq 事務消息,解決發送消息和本地事務不一致性問題:

 1.服務A向mq發一條prepare消息;

 2.發送失敗說明mq不可用,直接回滾事務返回失敗;

3.發送成功執行本地事務,向mq提交事務狀態;

4.如果服務A宕機了沒有向mq提交事務狀態;服務A(單機部署)恢復之後,mq會回查事務結果;

5.事務處理成功,mq會將消息可見,服務B拉取並消費消息。

 這個方案能很好的解決發送消息和本地事務一致性的問題,相對上面其他幾個方案,會好很多。不過在生產中可以根據具體情況進行方案選取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章