消息中間件(MQ)的相關知識

聲明:原文出處已在文末標出,本人出於學習,對其做了整理,收集乾貨,不作商業用途!

目錄

一、消息中間件的簡介

二、消息中間件(MQ)的使用場景(爲什麼要使用MQ)

2.1 解耦

2.2 異步

2.3 削峯

2.4 日誌處理

2.5 消息通訊

2.5.1 點對點通訊

2.5.2 發佈/訂閱通訊

三、消息中間件常用協議

3.1 AMQP協議

3.2 MQTT協議

3.3 STOMP協議

3.4 XMPP協議

3.5 其他基於TCP/IP自定義的協議

四、消息中間件訂閱模式

4.1 點對點模式

4.2 發佈/訂閱模式(也稱廣播模式)

4.3 推拉模型(根據消費者獲取消息的方式區分)

五、消息中間件的優勢及缺點

5.1 消息中間件的優點

5.1.1 系統解耦

5.1.2 提高系統響應時間

5.1.3 爲大數據處理架構提供服務

5.1.4 Java消息服務——JMS

5.2消息中間件的缺點

5.2.1 系統可用性降低

5.2.2 系統複雜性增加

六、常見的消息中間件(MQ)介紹?

6.1 RabbitMQ(優點、缺點、個人評價)

6.2 RocketMQ (優點、缺點、個人評價)

6.3 ActiveMQ(優點、缺點、個人評價)

6.4 ZeroMQ (優點、缺點、個人評價)

6.5 Kafka(優點、缺點、個人評價)

6.6  Redis

七、項目中如何選擇MQ(主流四大MQ)

八、常見問題解析

8.1 如何保證消息隊列是高可用的 

8.2 如何保證消息不被重複消費(如何保證消息隊列的冪等性)

8.3 如何保證消費的可靠性傳輸

8.4 如何保證消息的順序性

8.5 MQ積壓成數萬條數據怎麼辦

8.6 MQ設置了過期時間,數據丟失怎麼辦

8.7 MQ溢出怎麼辦


 

正文

一、消息中間件的簡介

       消息中間件(MOM),用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通信。本文主要講消息隊列,消息隊列(Message queue 即MQ)是在消息的傳輸過程中保存消息的容器。MQ負責兩個系統之間傳遞消息,這兩個系統可以是異構的,處於不同硬件、不同操作系統、用不同語言編寫,只需要簡單配置、以及簡單的調用幾個MQ的API,就可以互相通訊,你不必考慮底層系統和網絡的複雜性,MQ能夠應付多種異常情況,例如網絡阻塞、臨時中斷等等;消息隊列主要解決應用解耦,異步消息,流量削鋒等問題,實現高性能,高可用,可伸縮和最終一致性架構。使用較多的消息隊列有ActiveMQ,RocketMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ等,部分 數據庫RedisMySQL 以及 phxsql 也可實現消息隊列的功能。

二、消息中間件(MQ)的使用場景(爲什麼要使用MQ)

消息中間件的使用場景主要的有以下幾點:解耦、異步、削峯、日誌、消息通訊,下面逐個解釋:

2.1 解耦

傳統模式:

             

傳統模式的缺點:系統間耦合性太強,如上圖所示,系統A在代碼中直接調用系統B和系統C的代碼,如果將來D系統接入,系統                               A還需要修改代碼,過於麻煩!

中間件模式::

                     

中間件的優點:將消息寫入消息隊列,需要消息的系統自己從消息隊列中訂閱,從而系統A不需要做任何修改。

2.2 異步

傳統模式:

                  

傳統模式的缺點:一些非必要的業務邏輯以同步的方式運行,太耗費時間。

中間件模式:

                 

中間件模式優點:將消息寫入消息隊列,非必要的業務邏輯以異步的方式運行,加快響應速度。

2.3 削峯

傳統模式:

              

傳統模式的缺點:併發量大的時候,所有的請求直接懟到數據庫,造成數據庫連接異常。

中間件模式:

               

中間件模式的優點:系統A慢慢的按照數據庫能處理的併發量,從消息隊列中慢慢拉取消息。在生產中,這個短暫的高峯期積壓                                  是允許的,假如消息隊列的長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面。

流量削峯的典型應用:淘寶的雙11秒殺,團購搶購活動,一般因爲流量過大,導致流量暴增,應用掛掉。爲解決此問題, 一般                                        需要在應用前端加入消息隊列,一者可以控制活動的人數,二來也可以緩解短時間內高流量壓垮應用。

2.4 日誌處理

日誌處理是指將消息隊列用在日誌處理中,比如Kafka的應用。架構簡化如下

             

日誌採集:負責日誌數據採集,定時寫受寫入Kafka隊列;
Kafka消息隊列:負責日誌數據的接收,存儲和轉發;
日誌處理應用:訂閱並消費kafka隊列中的日誌數據 。

應用:解決大量日誌傳輸的問題。

2.5 消息通訊

消息通訊是指,消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊。比如實現點對點消息隊列,或者聊天室等。

2.5.1 點對點通訊

           

客戶端A和客戶端B使用同一隊列,進行消息通訊。

2.5.2 發佈/訂閱通訊

              

客戶端A,客戶端B,客戶端C,客戶端D 訂閱同一主題(topic),進行消息發佈和接收。實現類似聊天室效果。

消息通訊的典型應用:今日頭條的私信功能,因爲消息通信的數據不需要即時立即同步回來,不算核心數據,這樣可以降低系統                                      的負荷。

三、消息中間件常用協議

3.1 AMQP協議

AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不同產品,不同開發語言等條件的限制。
優點:可靠、通用

3.2 MQTT協議

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議,有可能成爲物聯網的重要組成部分。該協議支持所有平臺,幾乎可以把所有聯網物品和外部連接起來,被用來當做傳感器和致動器(比如通過Twitter讓房屋聯網)的通信協議。
優點:格式簡潔、佔用帶寬小、移動端通信、PUSH、嵌入式系統

3.3 STOMP協議

STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息協議,是一種爲MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議。STOMP提供一個可互操作的連接格式,允許客戶端與任意STOMP消息代理(Broker)進行交互。本博客之前寫了個小例子,可參考 https://blog.csdn.net/zxljsbk/article/details/79292656
優點:命令模式(非topic\queue模式)

3.4 XMPP協議

XMPP(可擴展消息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴展標記語言(XML)的協議,多用於即時消息(IM)以及在線現場探測。適用於服務器之間的準即時操作。核心是基於XML流傳輸,這個協議可能最終允許因特網用戶向因特網上的其他任何人發送即時消息,即使其操作系統和瀏覽器不同。
優點:通用公開、兼容性強、可擴展、安全性高,但XML編碼格式佔用帶寬大

3.5 其他基於TCP/IP自定義的協議

有些特殊框架(如:redis、kafka、zeroMq等)根據自身需要未嚴格遵循MQ規範,而是基於TCP\IP自行封裝了一套協議,通過網絡socket接口進行傳輸,實現了MQ的功能。


四、消息中間件訂閱模式

4.1 點對點模式

                           

過程:消息生產者(Product)生產消息發送到消息對列(Queue)中,然後消息消費者(Consumer)從queue中取出並且消費消息。

特點:消息被消費以後,Queue中不再有存儲,所以消息消費者不可能消費到已經被消費的消息。Queue支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費;Queue實現了負載均衡,當沒有消費者可用時,這個消息會被保存直到有一個可用的消費者。

4.2 發佈/訂閱模式(也稱廣播模式)

                 

過程:發佈者(Publisher)將消息發佈到Topic中,然後訂閱者(Subscriber)從Topic中取出並且消費信息。

特點:消息被一個訂閱者消費後,並沒有消失,而是儲存在Topic中,供所有的訂閱者消費。

兩者區別:這兩種模式主要區別或解決的問題就是發送到隊列的消息能否重複消費

4.3 推拉模型(根據消費者獲取消息的方式區分)

對於消費者而言有兩種方式從消息中間件獲取消息,即push和pull:

Push方式:由消息中間件主動地將消息推送給消費者,這種方式可以儘快的將消息發給消費者。
Pull方式:由消費者主動向消息中間件拉取消息,這種方式相比push方式會稍微增加消息的到達消費者的時間。

  問:如果消費者的處理消息的能力很弱(一條消息需要很長的時間處理),而消息中間件不斷地向消費者Push消息,消費者的緩             衝區可能會溢出,如何解決。

  答:如ActiveMQ的決絕辦法那就是  prefetch limit,當推送消息的數量到達了perfetch limit規定的數值時,消費者還沒有向消             息中間件返回確認的ACK(響應),消息中間件將不再繼續向消費者推送消息。Prefech limit 的值取多少、prefetchACK的值           怎麼設置,可以參考這個,也可自行百度   https://blog.csdn.net/qq_35508033/article/details/80255138

五、消息中間件的優勢及缺點

5.1 消息中間件的優點

5.1.1 系統解耦

       交互系統之間沒有直接的調用關係,只是通過消息傳輸,故系統侵入性不強,耦合度低。

5.1.2 提高系統響應時間

       例如原來的一套邏輯,完成支付可能涉及先修改訂單狀態、計算會員積分、通知物流配送幾個邏輯才能完成;通過MQ架構設計,就可將緊急重要(需要立刻響應)的業務放到該調用方法中,響應要求不高的使用消息隊列,放到MQ隊列中,供消費者處理。

5.1.3 爲大數據處理架構提供服務

        通過消息作爲整合,大數據的背景下,消息隊列還與實時處理架構整合,爲數據處理提供性能支持。

5.1.4 Java消息服務——JMS

       Java消息服務(Java Message Service,JMS)應用程序接口是一個Java平臺中關於面向消息中間件(MOM)的API,用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通信。 
JMS中的P2P和Pub/Sub消息模式:點對點(point to point, queue)與發佈訂閱(publish/subscribe,topic)最初是由JMS定義的。這兩種模式主要區別或解決的問題就是發送到隊列的消息能否重複消費(多訂閱)。

5.2消息中間件的缺點

5.2.1 系統可用性降低

       試想,本來其他系統只要運行好好的,那你的系統就是正常的。現在你非要加個消息隊列進去,那消息隊列掛了,你的系統不是呵呵了。因此,系統可用性降低。

5.2.2 系統複雜性增加

       要多考慮很多方面的問題,比如一致性問題、如何保證消息不被重複消費,如何保證保證消息可靠傳輸。因此,需要考慮的東西更多,系統複雜性增大。

六、常見的消息中間件(MQ)介紹?

6.1 RabbitMQ(優點、缺點、個人評價)

        RabbitMQ是使用Erlang語言開發的開源消息隊列系統,基於AMQP協議來實現,AMQP的主要特徵是面向消息,隊列,路由(包括點對點和發佈/訂閱),可靠性,安全,AMQP協議更多用在企業系統內,對數據一致性,穩定性和可靠性要求很高的場景,對性能和吞吐量的要求還在其次。

6.1.1 RabbitMQ優點

         ①併發性能極好。      

         ②支持長時間消費和消息事務。如果消費者沒有斷開連接,並且沒有確認消費,那麼rabbitmq會一直等待消費者消費完成。

         ③支持批量確認和異步確認(comfirm機制)。

         ④權限控制比較完善。

         ⑤有強大的WEB管理頁面。

6.1.2 RabbitMQ缺點

         ①只支持簡單集羣,對高級集羣模式支持不好。

         ②不支持負載均衡,要藉助LVS或者HAPROXY等技術實現。

         ③只能支持少量堆積,各種隊列和元數據的存儲需要大量的磁盤空間。

         ④Erlang語言開發,研究源碼有一定難度。

6.1.3 RabbitMQ個人評價

       RabbitMQ的特性適合長時間消費的應用場景,比如郵箱通知系統,短信通知系統。性能比ActiveMQ高,安全,可靠性強。但是不適合大數據的應用場合。

6.2 RocketMQ (優點、缺點、個人評價)

      RocketMQ是阿里開源的消息中間件,目前也已經孵化爲Apache頂級項目,它是純Java開發,具有高吞吐量,高可用性,適合大規模分佈式系統應用的特點,RocketMQ思路起源於kafka,它對消息的可靠傳輸及事務性做了優化,目前在阿里集團被廣泛應用於交易,充值,流計算,消息推送,日誌流式處理,binglog分發等場景。

6.2.1 RocketMQ 優點

          ①支持消息失敗重試、消息事務、消息回溯,高可靠的持久化策略,消息幾乎不會丟失。

          ②實時性好。RocketMQ使用長輪詢,同Push方式實時性一致,消息的投遞延時通常在幾個毫秒。

          ③支持大量堆積,持久化效率高,批量刷盤。

          ④對分佈式支持很好,使用nameserver管理集羣成員,支持動態擴展。

6.2.2 RocketMQ 缺點

          ①存儲方式只支持寫到磁盤。

          ②使用消息事務,確保了消息的可靠投遞,但是必然會導致併發性能下降,這個把雙刃劍。

6.2.3 RocketMQ個人評價

          高性能,滿足可靠性,滿足分佈式,支持水平擴展,主從之間的自由切換,它雖然非常完善,但是收費。

6.3 ActiveMQ(優點、缺點、個人評價)

       ActiveMQ是Apache出品(下一代產品爲Apollo),最流行的,能力強勁的開源消息總線,並且它是一個完全支持JMS規範的消息中間件其豐富的API,多種集羣構建模式使得他稱爲業界老牌消息中間件,在中小型企業中應用廣泛。

6.3.1 ActiveMQ優點

          ①產品成熟,在中等小型規模的場景有很多應用。

          ②功能齊全,支持多種恢復機制,支持事務,支持多種協議。

          ③Activemq高版本負載均衡做得比較好,高可用,支持動態擴展。

          ④AcitiveMQ很容易嵌入到spring的項目中。

6.3.2 ActiveMQ缺點

          ①存儲方式只能支持少量堆積。

          ②ActiveMQ默認的配置性能偏低,需要優化配置,但是配置文件複雜,ActiveMQ本身不提供管理工具,示例代碼少。

          ③只適合簡單集羣。

6.2.3 ActiveMQ個人評價

          ActiveMQ適合一般的事務性業務場合,不適合大數據應用的場合。在面對高併發的環境下,性能不是很好。

6.4 ZeroMQ (優點、缺點、個人評價)

      ZeroMQ號稱最快的消息隊列系統,尤其針對大吞吐量的需求場景。ZMQ能夠實現RabbitMQ不擅長的高級/複雜的隊列,但是開發人員需要自己組合多種技術框架,技術上的複雜度是對這MQ能夠應用成功的挑戰。ZeroMQ具有一個獨特的非中間件的模式,你不需要安裝和運行一個消息服務器或中間件,因爲你的應用程序將扮演了這個服務角色。你只需要簡單的引用ZeroMQ程序庫,可以使用NuGet安裝,然後你就可以愉快的在應用程序之間發送消息了。但是ZeroMQ僅提供非持久性的隊列,也就是說如果down機,數據將會丟失。其中,Twitter的Storm中使用ZeroMQ作爲數據流的傳輸。

6.4.1 ZeroMQ優點

          ①性能極好,吞吐量極大,併發性能極好,實時性極好。

          ②引用ZeroMQ程序庫即可在應用之間發送消息,拿來即用,產品能夠快速迭代迅速成型。

          ③可以構建複雜的隊列,處理邏輯可以定製。

          ④非持久化消息,對系統的存儲空間要求不大,但是可以處理成千上萬的數據,服務器成本低。

6.4.2 ZeroMQ缺點

          ①只有消息重傳機制,消息容易丟失。

          ②功能不夠完備,很多功能需要我們去實現,不適合複雜的業務。

6.4.3 ZeroMQ個人評價

        ZeroMQ適合大數據、實時處理、高頻計算、定製性強的應用場合,比如股票市場統計。由於對服務器的要求低,性 能極其優越,有利於小型企業的快速應用、軟件的快速迭代。

6.5 Kafka(優點、缺點、個人評價)

       Kafka是Apache下的一個子項目,開發語言爲scala,是一個高性能跨語言分佈式發佈/訂閱消息隊列系統,只支持主要的MQ功能,像一些消息查詢,消息回溯等功能沒有提供,畢竟是爲大數據準備的,在大數據領域應用廣。kafka主要特點是基於Pull的模式來處理消息消費,追求高吞吐量,一開始的目的就是用於日誌收集和傳輸,適合產生大量數據的互聯網服務的數據收集業務。

6.5.1 Kafka優點

       ①支持同步到數據庫,能與hadoop、hbase等建立數據管道;

       ②吞吐量極大,在一臺普通的服務器上既可以達到10W/s的吞吐速率;

       ③完全的分佈式系統,Broker、Producer、Consumer都原生自動支持分佈式,自動實現負載均衡;

       ④支持Hadoop數據並行加載,滿足像Hadoop的一樣的日誌數據和離線分析系統,但又要求實時處理的限制;

       ⑤通過Hadoop的並行加載機制統一了在線和離線的消息處理。

6.5.2 Kafka缺點

       長時間的消費,容易失敗。

6.5.3 Kafka個人評價

        kafka非常適合流式處理、大數據、單次消費時間較短的場合(日誌採集、處理)。由於不支持消息事務,對於交易系統、訂單系統不太適合

6.6  Redis

Redis 做爲一個基於內存的K-V數據庫,其提供了消息訂閱的服務,所以完全可以當做一個輕量級的MQ來使用,目前應用案例較少,且不方便擴展。

七、項目中如何選擇MQ(主流四大MQ)

綜合對比,建議如下:

    之前,ActiveMQ很火,官方一直對其維護,但是如今國內應用都越來越少,官方社區現在對ActiveMQ 5.x維護越來越少,幾個月才發佈一個版本,我個人不推薦用這個了;

       對於RabbitMQ,是erlang語言開發,性能極好,但 erlang 語言卻阻止了大量的 Java 工程師去深入研究和掌控它,對公司而言,幾乎處於不可控的狀態,但是確實人家是開源的,比較穩定的支持,社區活躍度也高;

     對於RocketMQ,如今越來越多的公司會去用 RocketMQ,接口簡單易用,而且畢竟在阿里大規模應用過,有阿里雙十一處理消息上百億之多,可以做到大規模吞吐,性能也非常好,還可以支撐大規模的topic數量,支持複雜MQ業務場景而且一個很大的優勢在於,阿里出品都是java系的,我們可以自己閱讀源碼,定製自己公司的MQ,但社區可能有突然黃掉的風險,對自己公司技術實力有絕對自信的,推薦用 RocketMQ,否則回去老老實實用 RabbitMQ 吧,人家有活躍的開源社區,絕對不會黃。

      對於kafka,   非常適合流式處理、大數據、單次消費時間較短的場合(日誌採集、處理)。

      綜上,個人認爲中小型公司,技術實力較爲一般,技術挑戰不是特別高,用 RabbitMQ 是不錯的選擇;大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇;如果是大數據領域的實時計算、日誌採集等場景,推薦 Kafka 。

八、常見問題解析

8.1 如何保證消息隊列是高可用的 

        由於系統使用了MQ,必然會導致系統可用性降低,那麼如何解決吶?以RabbitMQ爲例,談談如何保證系統的高可用。

        

8.2 如何保證消息不被重複消費(如何保證消息隊列的冪等性)

 造成重複消費的原因?

                

        無論是哪種消息隊列(MQ),造成重複消費的原因都類似,分兩種情況,

       一種是生產者和消息隊列之間產生的,生產者把消息發送到消息隊列,消息隊列收到後,會返回給生產者一個確認信息,只是不同的MQ用的不同的反饋機制(RabbitMQ是發送一個ACK確認消息,RocketMQ是返回一個CONSUME_SUCCESS成功標誌,kafka實際上有個offset的概念)。當網絡傳輸故障等原因,這個確認信息沒有返回到生產者,生產者認爲消息未發送成功,就會重新發送剛纔的信息,這樣就導致了MQ重複接收消息。

       另一種是消息隊列和消費者之間產生的,消息通過MQ到達消費者,消費者消費完畢之後,會返回一個確認信息,MQ就知道該消息被消費了。不同的MQ也是用的不同的反饋機制(RabbitMQ是發送一個ACK確認消息,RocketMQ是返回一個CONSUME_SUCCESS成功標誌,kafka實際上有個offset的概念)。當網絡傳輸故障等原因,這個確認信息沒有返回到MQ,導致MQ不知道該消息已經被消費過了,從而分給其他的消費者消費,這樣就導致了消息被重複消費。

      綜上,無論是上圖中的步驟“2”處的ACK丟失,還是步驟“4”處的ACK丟失,都可能導致消費者重複消費。

 如何解決?

       針對步驟“2”處的ACK丟失的解決辦法MQ系統內部生成一個inner-msg-id,該id全局唯一,由MQ生成,具備業務無關                                                                             性,對消息發送方和消息接收方屏蔽。

       針對步驟“4”處的ACK丟失的解決辦法

              由於步驟4處,經過了消費者,所以就和業務關係緊密,如下:

              1)如果要拿數據插入數據庫的話,可以設置個主鍵,避免重複。

              2)如果要拿數據寫入redis的話,就更沒問題了,redis天然冪等。

              3)如果不具備上面的條件,可以引入第三方介質來做消費記錄,就是在生產者生產出來消息時,就加一個全局的唯一                        的id,只要是消費過該消息,就將<id,message>以K-V的形式存入到redis中,等到以後的消費開始之前,先去redis                      中查下有無消費記錄即可。

8.3 如何保證消費的可靠性傳輸

每種MQ都要從三個角度來分析:生產者丟失數據、消息隊列丟失數據、消費者丟失數據

以RabbitMQ爲例:

1)生產者數據丟失的解決辦法

     ①事務機制:生產者發送數據之前開啓rabbitmq事務(channel.txSelet),此時,如果消息到消息隊列的途中出錯,就可以回滾事務(channel.txRollback),然後再繼續重發消息,如果消息隊列接收成功,就提交事務(channel.txCommit),但是該機制太耗性能,吞吐量就會大幅下降。

     ②confirm機制(推薦): 在生產者那裏設置開啓confirm模式之後,你每次寫的消息都會分配一個唯一的id(從1開始),當消息到達消息隊列後,會返回ACK確認消息,告訴生產者已經正確到達目的隊列了,如果RabiitMQ沒能處理該消息,則會發送一個Nack消息給你,告訴你這個消息接收失敗,你可以重試。而且你可以結合這個機制自己在內存裏維護每個消息id的狀態,如果超過一定時間還沒接收到這個消息的回調,那麼你可以重發。

        事務機制和cnofirm機制最大的不同在於,事務機制是同步的,你提交一個事務之後會阻塞在那兒,但是confirm機制是異步的,你發送個消息之後就可以發送下一個消息,然後那個消息rabbitmq接收了之後會異步回調你一個接口通知你這個消息接收到了。

2)消息隊列數據丟失的解決辦法

     處理消息隊列數據丟失的情況,可以採取開啓持久化磁盤的配置,這個持久化配置可以和confirm機制配合使用,即在消息持久化磁盤後,給生產者發送個ACK信號,這樣,即使在持久化磁盤之前RabbitMQ掛掉了,生產者沒有收到ACK信號,也會給消息隊列重發該條信息。

那麼如何持久化呢,其實也很容易,就下面兩步
①、將queue的持久化標識durable設置爲true,則代表是一個持久的隊列;
②、發送消息的時候將deliveryMode=2;
這樣設置以後,RabbitMQ就算掛了,重啓後也能恢復數據。

3)消費者數據丟失的解決辦法

      消費者數據丟失因爲RabbitMQ採用了自動確認消息模式。這種模式下,消費者會自動確認收到信息。這時消息隊列會立即將已發送的消息刪除,這種情況下如果消費者出現異常而沒能處理該消息,就會丟失該消息。解決辦法就是關閉RabbitMQ的自動確認消息(自動ACK),改爲手動的,每次代碼裏的確保消費者消費完消息後,手動發送ACK給消息隊列,這樣當消費者掛掉,消息隊列一定時間內沒有收到ACK,就會把該消息分配給別的消費者去消費,這樣消息就不會丟失了。

     不同的MQ的消息數據丟失的解決辦法不同,可自行百度。

8.4 如何保證消息的順序性

       舉個簡單的例子,喫瓜子的過程(消息1:拆包裝,消息2:剝皮,消息3::喫到瓜子仁),相當於生產者產生的三條信息,把他們發到消息隊列中,正常的消費順序應該是:消息1->消息2->消息3,但這時只有一個隊列(queue),多個消費者(consumer),此時就有可能出現某一個消費者消費了信息3,卻沒有消費信息1和信息2(即喫到了瓜子仁,卻沒有拆包裝和剝皮),這樣顯然不合理。所以我們就需要想辦法,讓這個順序依次執行。

1.在 MQ 層面順序處理

        如RabbitMQ中,可以拆分多個queue,每個queue對應一個consumer,consumer內部用內存隊列做排隊,然後分發給底層不同的worker來處理。

                     

2.在業務邏輯處理順序性

         在 MQ 層面支持消息的順序處理開銷太大,爲了極少量的需求,增加整體上的複雜度得不償失。可以使用msg-id判斷消息的順序(需要全局存儲,記錄消息的執行狀態)。

8.5 MQ積壓成數萬條數據怎麼辦

       恢復consumer消費速度法: 正常情況下,一個消費者一秒是1000條,一秒3個消費者是3000條,一分鐘是18萬條,1000多萬條,所以如果你積壓了幾百萬到上千萬的數據,即使消費者恢復了,也需要大概1小時的時間才能恢復過來,但是假如這時生產者不斷的推數據過來,很有可能導致MQ滿了,然後數據溢出,此方法着實不推薦。

       緊急擴容法(推薦):先修復consumer的問題,確保其恢復消費速度,然後將現有cnosumer都停掉。新建一個topic,partition是原來的10倍,臨時建立好原先10倍或者20倍的queue數量。然後寫一個臨時的分發數據的consumer程序,這個程序部署上去消費積壓的數據,消費之後不做耗時的處理,直接均勻輪詢寫入臨時建立好的10倍數量的queue。接着臨時徵用10倍的機器來部署consumer,每一批consumer消費一個臨時queue的數據。這種做法相當於是臨時將queue資源和consumer資源擴大10倍,以正常的10倍速度來消費數據。等快速消費完積壓數據之後,得恢復原先部署架構,重新用原先的consumer機器來消費消息。

8.6 MQ設置了過期時間,數據丟失怎麼辦

         例如RabbitMQ是可以設置過期時間的,就是TTL,如果消息在queue中積壓超過一定的時間就會被RabbitMQ給清理掉,這個數據丟失了。

解決辦法:批量重導法:可以等到夜深人靜的時候,將丟失的那批數據,寫個臨時程序,一點一點的查出來,然後重新灌入mq裏面去,把因爲過期時間丟的數據給他補回來。

8.7 MQ溢出怎麼辦

       當MQ消息太多,而消費者消費的速度又太慢,導致MQ溢出了,此時就用上文中的8.5的緊急擴容法,然後加上8.6的批量重導法,把溢出的數據補回來就好了。

參考:

https://www.cnblogs.com/rjzheng/p/8994962.html【原創】分佈式之消息隊列複習精講

https://blog.csdn.net/wqc19920906/article/details/82193316(消息中間件(一)MQ詳解及四大MQ比較)

https://blog.csdn.net/glory1234work2115/article/details/51728172(RPC和MQ區別)

https://www.cnblogs.com/FlowRainFlySnow/p/4628673.html消息中間件選型

https://blog.csdn.net/nsxqf/article/details/80600330(點對點/發佈訂閱)

https://www.jianshu.com/p/1d4455ed9d03(MQ常見問題及解決方案)

https://blog.csdn.net/u010775025/article/details/86134374(中間件對比----Kafka、ActiveMQ、RabbitMQ及RocketMQ性能對比)

https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959966&idx=1&sn=068a2866dcc49335d613d75c4a5d1b17&chksm=bd2d07428a5a8e54162ad8ea8e1e9302dfaeb664cecc453bd16a5f299820755bd2e1e0e17b60&scene=21#wechat_redirect(MQ,如何做到消息必達)

https://www.jianshu.com/p/2838890f3284(Rocketmq、kafka、Rabbitmq的詳細對比         二、RocketMQ集羣概述)

https://blog.csdn.net/lin451791119/article/details/79943315(Kafka、rabbitmq、zeromq、rocketmq、activemq綜合對比(二))

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