掌握之分佈式-3.消息隊列

掌握高併發、高可用架構

第三章 分佈式

本章介紹分佈式架構的底層技術。主要說明面試過程中可能被問到的技術點。

第三節 消息隊列(MQ,Message Queue)

消息隊列 MQ JMS AMQP ActiveMQ RabbitMQ RocketMQ kafka

1. 什麼是消息隊列

可以把消息隊列簡單理解爲存放消息的容器,並且當我們需要消息的時候可以取出消息供自己使用。消息隊列是分佈式系統中重要的中間件,它可以通過異步操作來實現提高系統性能、流量削峯、降低系統耦合。

目前比較流行的消息隊列有:ActiveMQ、RabbitMQ、RocketMQ、Kafka

2. 爲何要用消息隊列,它的優勢

消息隊列的優勢主要體現在:

  • 通過異步處理來提高系統性能

    img

    使用了消息隊列後,用戶的請求發送到消息隊列後就返回了,由消息隊列的消費者把消息異步的寫到數據庫。由於消息隊列服務器的處理速度大於數據庫,所以系統性能大幅提高

  • 降低系統的耦合性

    img

    使用了消息隊列後,應用之間不再是強耦合關係,各個應用從消息隊列獲取需要的消息,從而降低耦合

  • 限流削峯

    購物網站的秒殺活動,在秒殺開始的一瞬間流量巨大,可能會導致系統無法處理而崩潰。加入消息隊列後,用戶請求都會放入消息隊列,系統處理則從消息隊列獲取數據,不至於導致系統崩潰

    1. 請求先入消息隊列,而不是直接交給業務處理,做了一次緩衝,極大的降低了系統的壓力
    2. 隊列長度可以進行限制,後面的請求無法入隊,就可以直接拋棄了
3. 使用消息隊列帶來的問題
  • 系統可用性降低:加入MQ後,需要考慮服務器宕機的問題
  • 系統複雜性提高:消息丟失重複消費消息傳遞的順序性
  • 一致性問題:消息被正確的消費
4. JMS VS AMQP

JMS,Java Message Service即Java消息服務,它是消息服務的規範。JMS API允許應用程序組件基於JMEE平臺創建 、發送、接收、讀取消息。它使分佈式通信耦合性降低、消息服務更加可靠

ActiveMQ就是基於JMS規範實現的

JMS支持兩種消息模型:

  • 點對點(P2P)模型

    img

    使用隊列(Queue)來滿足生產者消費者模式,一條消息只能被一個消費者消費

  • 發佈/訂閱(Pub/Sub)模型

    img

    發佈-訂閱模型使用主題(Topic)作爲消息通信載體,發佈者發佈一條消息,該消息通過主題傳遞給所有的訂閱者

JMS支持的五種消息格式

  • StreamMessage,Java原始值的數據流
  • MapMessage,鍵值對
  • TextMessage,字符串
  • ObjectMessage,序列化的對象
  • BytesMessage,字節數據流

AMQP,Advanced Message Queuing Protocol,高級消息隊列協議(二進制應用層協議)。它是一個協議,兼容JMS。基於它實現的消息隊列,不收客戶端、中間件的開發語言限制

RabbitMQ就是基於AMQP實現的

比較內容 JMS AMQP
定義 JMS API,是一種規範 是一個協議
跨語言 否,僅支持JAVA
誇平臺
消息模型 點對點模型、發佈-訂閱模型 提供了五種消息模型:<br />1.direct exchange<br />2.fanout exchange<br />3.topic change<br />4.header exchange<br />5.system exchange<br />後四種和發佈訂閱僅是在路由機制上做了更詳細的劃分
消息類型 上述的五種消息格式 byte[] 二進制
5. 消息隊列選型

比較目前流行的四種消息隊列

特性 ActiveMQ RabbitMQ RocketMQ Kafka
開發語言 java erlang java scala
單機吞吐量 萬級(最差) 萬級(其次) 十萬級(最高) 十萬級(次之)
時效性 ms級 us級 ms級 ms以內
可用性 基於Zookeeper <br />+ LevelDB的<br />master-slave模式 master/slave模式<br />master提供服務<br />slave僅做備份 多master模式<br />多master多slave異步複製模式<br />多master多slave同步雙寫模式 replica機制,<br />leader宕機備份自動頂替,<br />並重新選舉leader(基於Zookeeper)
功能特性 成熟產品,社區不活躍,文檔齊全 併發能力強,性能好,管理界面豐富 比較成熟,擴展性佳 只提供主要的MQ功能,在大數據領域應用廣
消息推拉 pull,push都支持 pull,push都支持 pull,push都支持 pull
6. 如何保證不被重複消費

什麼情況會發生重複消費呢?正常情況下,消費者在消費消息完成後,會發送一個確認消息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息隊列中刪除。因爲網絡傳輸等故障,導致確認消息沒有傳送到消息隊列,繼而消息隊列不知道該消息已被消費,再次將消息分發消費了

這個問題在不同的場景下有不同的解決方案,主要是在消費方來解決重複問題

  • 消息用作DB的insert操作,此時可以把消息作爲一個主鍵,當出現重複消費時,就會主鍵衝突,自然就避免了
  • 消息用作Redis的set操作,此時,因爲set操作會覆蓋上一個值 ,但是兩次的值一樣,也是無所謂的
  • 最壞的情況下,可以準備第三方介質來存儲消費的消息。比如Redis,每次操作時都去Redis中查看是否之前操作過
7. 如何保證數據不丟失

消息丟失主要分爲:生產者丟失、消息隊列丟失、消費者丟失

每種MQ都有不同的處理,這裏就不詳細論述了

Topic模式

參考資料

一個用消息隊列 的人,不知道爲啥用 MQ,這就有點尷尬

新手也能看懂,消息隊列其實很簡單

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