消息隊列 ActiveMQ 、RocketMQ 、RabbitMQ 和 Kafka 如何選擇?

 

「 預計閱讀 6 分鐘 」

旁白:這是一篇拖更了N久的文章...0.0(看不見我~)html

往期回顧前端

前端框架 jQuery 和 Vue 如何選擇?java

安全框架 Shiro 和 Spring Security 如何選擇?git

正文程序員

 

消息隊列(MQ)安全

在百度百科中,消息隊列(MQ)是這麼解釋的:「消息隊列」是在消息的傳輸過程當中保存消息的容器(可存可取)。前端框架

它是分佈式系統中重要的組件,使用消息隊列主要是爲了經過異步處理提升系統性能和削峯和下降系統耦合性服務器

  • 異步處理:多應用對消息隊列中同一消息進行處理,應用間併發處理消息,相比較串行處理,減小處理時間;微信

  • 應用耦合:多應用經過消息隊列對同一消息進行處理,避免調用接口失敗致使整個過程失敗;網絡

  • 限流消峯:普遍應用於秒查或搶購活動中,避免某一刻流量過致使應用系統掛掉的狀況;

目前使用較多的消息隊列有 ActiveMQ 、RocketMQ 、RabbitMQ 和 Kafka 等。

消息隊列的兩種模式
消息隊列包括兩種模式:點對點模式 和 發佈/訂閱模式。
1)點對點模式

點對點模式下包括三個角色:

  • 消息隊列

  • 發送者 (生產者)

  • 接收者(消費者)

消息發送者生產消息發送到queue中,而後消息接收者從queue中取出而且消費消息。消息被消費之後,queue中再也不有存儲,因此消息接收者不可能消費到已經被消費的消息。

點對點模式特色:

  • 每一個消息只有一個接收者(Consumer)(即一旦被消費,消息就再也不在消息隊列中);

  • 發送者和接收者間沒有依賴性,發送者發送消息以後,無論有沒有接收者在運行,都不會影響到發送者下次發送消息;

  • 接收者在成功接收消息以後需向隊列應答成功,以便消息隊列刪除當前接收的消息;

2)發佈/訂閱模式

發佈/訂閱模式下包括三個角色:

  • 角色主題(Topic)

  • 發佈者(Publisher)

  • 訂閱者(Subscriber)

發佈者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。

發佈/訂閱模式特色:

  • 每一個消息能夠有多個訂閱者;

  • 發佈者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須建立一個訂閱者以後,才能消費發佈者的消息。

  • 爲了消費消息,訂閱者須要提早訂閱該角色主題,並保持在線運行;

異步處理

具體場景:用戶爲了使用某個應用,進行註冊,系統須要發送註冊郵件和註冊短信。

對於該流程有兩種處理方式:並行和串行。

1)串行處理:寫入註冊信息後,先發送註冊郵件,再發送註冊短信。

這種方式下,須要等發送短信處理完成後才完成註冊。

2)並行處理:寫入註冊信息後,同時處理髮郵件和發短信。

這種方式下,須要等發送短信和發送郵件處理完成後才完成註冊。

假設上面三個子系統處理耗時均爲:50ms,且不考慮網絡延遲,系統卡頓等因素,則總的處理時間爲:
串行:50ms + 50ms + 50 ms = 150ms
並行:50ms + 50ms = 100ms
使用消息隊列結果將如何呢?
若使用消息隊列,寫入完註冊信息後,再將信息寫入消息隊列就能直接返回成功給客戶端了,而後註冊完成。
如今總的響應時間依賴於寫入消息隊列的時間,而寫入消息隊列的時間是很快的,基本能夠忽略不計。所以總的處理時間相比串行提升了 2 倍,相比並行提升了 1 倍。
應用解耦
具體場景:A 系統每次產生數據時,都要將數據發給 BC 兩個系統(經過接口調用)。這個時候新增了一個 D 系統,以下圖:

在這個場景中,A 系統和其餘幾個系統亂七八糟的耦合在一塊兒,當 A 系統中產生一條數據時,須要將數據發給各個系統。
每次項目中新增了系統,A 系統都須要修改代碼,還要時刻擔憂那個系統掛掉了,信息沒發送過去要不要重發,那個系統又不要該數據了,這時求 A 系統負責人的心理陰影...
若是使用 MQ,A 系統產生一條數據後,只須要插入到 MQ 裏面去,那個系統須要就去 MQ 裏消費。若是新增了一個系統,那麼訂閱 MQ 的消息便可;同理那個系統再也不須要該數據,那麼只要取消訂閱就好了。

經過一個 MQ, Pub/Sub 發佈訂閱消息模型,A 系統就跟其餘系統實現解耦了。
限流削峯
具體場景:某電商網站開展秒殺活動,通常因爲瞬間訪問暴增,服務器收到請求過大,可能出現沒法處理請求或崩潰的狀況。

加入消息隊列後,系統就能夠從消息隊列中讀取數據,至關於作了一次緩衝,超出系統處理以外的請求會積壓在消息隊列中,等高峯期已過,就會快速將積壓在隊列中的數據處理完。
消息隊列有什麼優缺點
優勢上面已經說了,就是在特殊場景下有其對應的好處,解耦、異步、削峯。
缺點有如下幾個:
  • 系統可用性下降
    系統引入的外部依賴越多,越容易掛掉。原本你就是 A 系統調用 BCD 三個系統的接口就行了,人 ABCD 四個系統好好的,沒啥問題,你偏加個 MQ 進來,萬一 MQ 掛了咋整,MQ 一掛,整套系統崩潰的,你不就完了?如何保證消息隊列的高可用,能夠點擊這裏查看。
  • 系統複雜度提升
    硬生生加個 MQ 進來,你怎麼保證消息沒有重複消費?怎麼處理消息丟失的狀況?怎麼保證消息傳遞的順序性?頭大頭大,問題一大堆,痛苦不已。
  • 一致性問題
    A 系統處理完了直接返回成功了,人都覺得你這個請求就成功了;可是問題是,要是 BCD 三個系統那裏,BD 兩個系統寫庫成功了,結果 C 系統寫庫失敗了,咋整?你這數據就不一致了。
因此消息隊列實際是一種很是複雜的架構,你引入它有不少好處,可是也得針對它帶來的壞處作各類額外的技術方案和架構來規避掉,作好以後,系統複雜度提高了一個數量級,也許是複雜了 10 倍。可是關鍵時刻,用,仍是得用的。
RabbitMQ/ActiveMQ/RocketMQ/Kafka對比
這裏列舉了上述四種消息隊列的差別對比(圖片來源:https://www.cnblogs.com/javalyy/p/8856731.html):
圖片來源(https://doocs.gitee.io/advanced-java/#/docs/high-concurrency/why-mq)
總結
通常業務系統要引入 MQ,最先你們都是用 ActiveMQ,可是如今你們用的很少了,沒通過大規模吞吐量場景的驗證,社區也不是很活躍,不推薦使用。
中小型公司,技術實力較爲通常,技術挑戰不是特別高,用 RabbitMQ 是不錯的選擇,大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇。
若是是高性能分佈式、大數據領域的實時計算、日誌採集等場景,用 Kafka 是業內標準。

普遍來講,電商、金融等對事務性要求很高的,能夠考慮RabbitMQ和RocketMQ,對性能要求高的可考慮Kafka。

 
若是你以爲文章不錯,歡迎在看、轉發、讚揚一條龍,你的支持就是我最大的動力。
 

本文原發於 同名微信公衆號「程序員的成長之路」,回覆「1024」你懂得,給個讚唄。

回覆 [ 520 ] 領取程序員最佳學習方式

回覆 [ 256 ] 查看 Java 程序員成長規劃

相關文章
相關標籤/搜索