引入消息隊列須要考慮的問題

參考文章:互聯網 Java 工程師進階知識徹底掃盲java

I.場景說明(爲什麼要引入)

  1. 解耦
>> 下降系統耦合度
複製代碼
  1. 異步
>> 提高系統響應速度
複製代碼
  1. 削峯
>> 抵抗請求高峯時期
複製代碼

爲何使用消息隊列?消息隊列有什麼優勢和缺點?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什麼優勢和缺點?git

II.衆多消息隊列,孰優孰略?(如何選擇)

特性 ActiveMQ RabbitMQ RocketMQ Kafka
單機吞吐量 萬級 萬級 十萬級,支持高吞吐 十萬級,支持高吞吐
時效性 ms級 微秒級 ms級 ms級之內
可用性 高可用(基於主從架構) 高可用(基於主從架構) 高可用 分佈式架構 高可用,分佈式,一個數據多個副本
消息可靠性 有較低機率丟失 基本不丟 參數配置可作到0丟失 參數配置能夠作到0丟失
功能支持 沒通過大規模吞吐量場景的驗證,社區也不是很活躍 基於 erlang 開發,併發能力很強,性能極好,延時很低,開源,比較穩定的支持,活躍度也高; 功能較爲完善,仍是分佈式的,擴展性好 功能較爲簡單,主要支持簡單的 MQ 功能,在大數據領域的實時計算以及日誌採集被大規模使用,社區活躍度很高
綜上,各類對比以後,有以下建議:

最先你們都用 ActiveMQ,可是如今確實你們用的很少了,沒通過大規模吞吐量場景的驗證,社區也不是很活躍;

後來你們開始用 RabbitMQ,可是確實 erlang 語言阻止了大量的 Java 工程師去深刻研究和掌控它,對公司而言,
幾乎處於不可控的狀態,可是確實人家是開源的,比較穩定的支持,活躍度也高;

不過如今確實愈來愈多的公司會去用 RocketMQ,確實很不錯,畢竟是阿里出品,
但社區可能有忽然黃掉的風險(目前 RocketMQ 已捐給 Apache,但 GitHub 上的活躍度其實不算高)對本身公司
技術實力有絕對自信的,推薦用 RocketMQ,不然回去老老實實用 RabbitMQ 吧,人家有活躍的開源社區,
絕對不會黃。

因此中小型公司,技術實力較爲通常,技術挑戰不是特別高,
用 RabbitMQ 是不錯的選擇;大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇。
若是是大數據領域的實時計算、日誌採集等場景,用 Kafka 是業內標準的,絕對沒問題,社區活躍度很高,
絕對不會黃,況且幾乎是全世界這個領域的事實性規範。
複製代碼

III.引入消息隊列可能遇到的問題

  1. 如何保證消息的高可用?

    RabbitMQ 能夠開啓鏡像集羣模式,在鏡像集羣模式下, 你建立的 queue,不管元數據仍是 queue 裏的消息都會存在於多個實例上, 就是說,每一個 RabbitMQ 節點都有這個 queue 的一個完整鏡像, 包含 queue 的所有數據的意思。而後每次你寫消息到 queue 的時候, 都會自動把消息同步到多個實例的 queue 上。github

    點擊查看更多詳細解答數據庫

  2. 如何保證消息重複消費的問題(冪等性)?

    首先你的明白重複消費會出現什麼問題,爲何要保證冪等性。舉個例子: 若是消費者乾的事兒是拿一條數據就往數據庫裏寫一條,你可能就把數據在數據庫裏插入了 2 次, 那麼數據就錯了。其實重複消費不可怕, 可怕的是你沒考慮到重複消費以後,怎麼保證冪等性。 解決: 每一個消息加一個全局惟一的序號,根據序號判斷這條消息是否處理過, 而後再根據本身的業務場景進行處理。或更新或丟棄。架構

    點擊查看更多詳細解答併發

  3. 如何處理消息丟失問題(消息的可靠性傳輸)?

    1. 消息生產者把消息搞丟了: RabbitMQ開啓 confirm 模式,若是寫入了 RabbitMQ 中,RabbitMQ 會給你回傳一個 ack 消息, 告訴你說這個消息 ok 了。 若是 RabbitMQ 沒能處理這個消息,會回調你的一個 nack 接口,告訴你這個消息接收失敗,你能夠重試。 並且你能夠結合這個機制本身在內存裏維護每一個消息id的狀態, 若是超過必定時間還沒接收到這個消息的回調,那麼你能夠重發。
    2. MQ本身搞丟了數據: RabbitMQ能夠開啓持久化
    3. 消費端丟失了數據: RabbitMQ默認是自動ack的,也就是說消息到了消費端,就會自動確認已經消費了這條消息, 這時候可能你消費端剛拿到數據,而後掛了,那這條消息不就丟失了。 關閉RabbitMQ的自動確認,每次消費端邏輯處理完的時候, 在程序裏確認消費完成,通知MQ,這樣就保證了在消費端不會丟失了

    點擊查看更多詳細解答異步

  4. 如何保證消息的順序性?

    1. RabbitMQ: 拆分多個 queue,每一個 queue 一個 consumer,就是多一些 queue 而已,確實是麻煩點; 或者就一個 queue 可是對應一個 consumer
    2. Kafka: 一個 topic,一個 partition,一個 consumer,內部單線程消費,單線程吞吐量過低, 通常不會用這個。 寫 N 個內存 queue,具備相同 key 的數據都到同一個內存 queue;而後對於 N 個線程, 每一個線程分別消費一個內存 queue 便可,這樣就能保證順序性。

    點擊查看更多詳細解答分佈式

  5. 如何處理消息積壓的問題?消息過時失效問題?

    這種問題出現通常就是消費端出現問題了,致使大量消息積壓。 解決辦法: 修復consumer,恢復其消費能力,而後等待consumer消費完。 什麼?等待過久了? 消息積壓到幾百萬到上千萬數據時,那就有點蛋疼了,確實要好幾個小時,那就再提供一種解決方案 先修復 consumer 的問題,確保其恢復消費速度,而後新建一個 topic,partition 是原來的 10 倍,臨時創建好原先 10 倍的 queue 數量。 而後寫一個臨時的分發數據的 consumer 程序,這個程序部署上去消費積壓的數據, 消費以後不作耗時的處理,直接均勻輪詢寫入臨時創建好的 10 倍 數量的 queue。接着臨時徵用 10 倍的機器來部署consumer,每一批consumer消費一個臨時queue的數據。 這種作法至關因而臨時將 queue 資源 和 consumer 資源擴大 10 倍,以正常的 10倍速度來消費數據。等快速消費完積壓數據以後, 得恢復原先部署的架構,從新用原先的 consumer 機器來消費消息 如何處理消息過時失效問題 消息失效這沒得辦法了呀,只能怪當初設置失效時間的時候沒考慮到這個問題了, 可有可無的還好,要是重要的相似於訂單相關方面的消息,能夠寫個臨時程序, 根據訂單號把丟失的相關消息全查出來,補上。性能

    點擊查看更多詳細解答大數據

相關文章
相關標籤/搜索