RabbitMQ 核心概念及工作原理
什麼是 MQ
MQ 全稱是 Message Queue,消息的隊列,因爲是隊列,所以遵循 FIFO 先進先出的原則,它是一種跨進程的通信機制,用於上下游傳遞消息。在互聯網架構中,MQ 是一種非常常見的上下游 “邏輯解耦 + 物理解耦” 的消息通信服務。
爲什麼使用 MQ
①流量削峯:解決高併發問題
例如秒殺活動,可能會在短時間內產生大量請求同時打到服務端,如果後端對每個請求都進行數據庫讀寫操作,定會造成服務器壓力過大,產生服務異常甚至不可用。我們可以通過使用 MQ 實現流量緩衝,將所有請求先放入消息隊列中,服務端每次處理業務先從消息隊列獲取,從而實現流量削峯,解決高併發問題。
②應用解耦:提升系統可用性
例如電商應用中有訂單系統、庫存系統、物流系統、支付系統,當用戶創建訂單後,先後調用庫存系統、物流系統、支付系統,任何一個子系統出了故障,都會造成下單失敗。引入消息隊列後,系統間耦合調用的問題會減少,任何一個子系統出現故障都不會影響用戶下單,子系統故障恢復後,會繼續處理消息,提升系統可用性。
③異步處理:提升響應速度
當用戶在客戶端提交了一個同步請求,後端處理需要耗時很久才能響應,這對用戶體驗來說無疑是致命的。如果說用戶並不關心請求是否處理完成,對於一些耗時的非事務性的業務處理,可以使用消息隊列異步請求的方式,將請求信息放入消息隊列,直接返回客戶端響應,後端監聽隊列自行處理,提升響應速度。
常見 MQ 分類
①Kafka
號稱大數據的殺手鐧,談到大數據領域內的消息傳輸,則繞不開 Kafka,這款爲大數據而生的消息中間件,以其百萬級 TPS 的吞吐量名聲大噪,迅速成爲大數據領域的寵兒,在數據採集、傳輸、存儲的過程中發揮着舉足輕重的作用。
優點:單機寫入 TPS 約在百萬條 / 秒,最大的優點,就是吞吐量高。時效性 ms 級可用性非常高,kafka 是分佈式的,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用,消費者採用 Pull 方式獲取消息,消息有序,通過控制能夠保證所有消息被消費且僅被消費一次;有優秀的第三方 Kafka Web 管理界面 Kafka-Manager;在日誌領域比較成熟,被多家公司和多個開源項目使用;主要支持簡單的 MQ 功能,在大數據領域的實時計算以及日誌採集場景中大規模使用。
缺點:單機超過 64 個隊列 / 分區,Load 會發生明顯的飆高現象,隊列越多,Load 越高,發送消息響應時間變長,使用短輪詢方式,實時性取決於輪詢間隔時間,消費失敗不支持重試;支持消息順序,但是一臺代理宕機後,就會產生消息亂序,社區更新較慢。
②ActiveMQ
ActiveMQ 是一款非常古老的 MQ。
優點:單機吞吐量萬級,時效性 ms 級,可用性高,基於主從架構實現高可用性,消息可靠,丟失數據的概率較低。
缺點:官方社區現在對 ActiveMQ 5.x 維護越來越少, 高吞吐量場景較少使用。
③RocketMQ
RocketMQ 是阿里巴巴開源產品,用 Java 語言實現,在設計時參考了 Kafka,並做出些改進, 被阿里巴巴廣泛應用。
優點:單機吞吐量十萬級,可用性非常高,分佈式架構,**消息可以做到 0 丟失,**MQ 功能較爲完善,擴展性好,支持 10 億級別的消息堆積,不會因爲堆積導致性能下降。
缺點:支持的客戶端語言不多,目前是 java 及 C++,其中 C++ 不成熟;社區活躍度一般,沒有在 MQ 核心中實現 JMS 等接口,有些系統要遷移需要修改大量代碼。
④RabbitMQ
2007 年發佈,是一個在 AMQP(高級消息隊列協議)基礎上完成的,可複用的企業消息系統,是當前最主流的消息中間件之一。
優點:由於 erlang 語言的高併發特性,性能較好;吞吐量到萬級,MQ 功能比較完備、健壯、穩定、易用、跨平臺、支持多種語言,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP 等,支持 AJAX 文檔齊全;開源提供的管理界面非常棒,用起來很好用,社區活躍度高,更新頻率相當高。
缺點:商業版需要收費,學習成本較高
參考資料:
https://www.imooc.com/article/290040
https://rocketmq.apache.org/docs/motivation/
RabbitMQ 工作原理
-
生產者(Producer)通過信道(Channel)把消息發送給交換機(Exchange),當創建交換機時需要指定類型(四種類型:直接 Direct,扇出 Fanout ,主題 Topic ,消息頭 Headers );
-
交換機(Exchange)接收消息並且負責對消息進行路由,交換機根據消息的屬性來把消息分發到不同的隊列(Queue)上;
-
消息(Message)會一直留在隊列裏直到被消費者(Consumer)消費。
RabbitMQ 核心概念
-
生產者(Producer):發送消息的應用。
-
消費者(Consumer):接收消息的應用。
-
隊列(Queue):存儲消息的緩存。
-
消息(Message):由生產者通過 RabbitMQ 發送給消費者的信息。
-
連接(Connection):連接 RabbitMQ 和應用服務器的 TCP 連接。
-
信道(Channel):連接裏的一個虛擬通道,通過消息隊列發送或者接收消息時,都是通過信道進行的。
-
交換機(Exchange):交換機負責從生產者那裏接收消息,並根據交換類型分發到對應的消息隊列裏。
-
綁定(Binding):綁定是隊列和交換機的一個關聯連接。
-
路由鍵(Routing Key):路由鍵是供交換機查看並根據鍵來決定如何分發消息到隊列的一個鍵,路由鍵可以說是消息的目的地址。
-
代理(Broker):接收和分發消息的應用,RabbitMQ Server 就是 Message Broker。
-
虛擬主機(Virtual host):出於多租戶和安全因素設計的,把 AMQP 的基本組件劃分到一個虛擬的分組中,類似於網絡中的 namespace 概念。當多個不同的用戶使用同一個 RabbitMQ server 提供的服務時,可以劃分出多個 vhost,每個用戶在自己的 vhost 創建 exchange/queue 等。
RabbitMQ 的高級應用
①死信隊列
死信隊列(DLX,Dead-Letter-Exchange),利用 DLX,當消息在一個隊列中變成無法被消費的消息(dead message)之後,它能被重新 publish 到另一個 Exchange,這個 Exchange 就是 DLX。
消息變成死信的幾種情況:
1、 消息被拒絕(
channel.basicReject/channel.basicNack)並且 request=false;
2、 消息在隊列的存活時間超過設置的生存時間(TTL)時間;
3、 隊列達到最大長度(隊列滿了,無法再添加數據到隊列中)。
DLX 也是一個正常的 Exchange,和一般的 Exchange 沒有區別,它能在任何的隊列上被指定,實際上就是設置某個隊列的屬性。
死信隊列的設置:
1、首先,需要設置死信隊列的 Exchange 和 queue,然後進行綁定;
2、然後,我們進行正常聲明交換機、隊列、綁定,只不過我們需要在隊列機上一個參數即可:arguments.put(“x-dead-letter-exchange”,”dlx.exchange”);這樣消息在過期、被拒絕、隊列在達到最大長度時,消息就可以直接路由到死信隊列。
②延遲隊列
基於
rabbitmq_delayed_message_exchange 插件,實現延遲隊列效果。它是一種新的交換類型,該類型消息支持延遲投遞機制消息傳遞後並不會立即投遞到目標隊列中,而是存儲在 mnesia(一個分佈式數據系統)表中,當達到投遞時間時,才投遞到目標隊列中。使用延遲隊列,可以有效解決定時任務帶來的系統壓力以及業務處理時效性等問題。
應用場景:
-
訂單在 30 分鐘之內未支持,則自動取消訂單
-
工單在 60 分鐘之內仍未處理,則發送消息提醒
-
預定會議室後,在預定時間前 10 分鐘,通知提醒各參會人員
-
………………………………
③隊列冪等性
冪等性的實質是:對於一個資源,不管你請求一次還是請求多次,對該資源本身造成的影響應該是相同的,不能因爲重複相同的請求而對該資源重複造成影響。注意關注的是請求操作對資源本身造成的影響,而不是請求資源返回的結果。
MQ 消費者的冪等性一般使用全局 ID 或者寫個唯一標識(比如流水號 / 時間戳 / UUID / 訂單號)來判斷該消息是否已消費過,也可以利用 redis 執行 setnx 命令,天然具有冪等性,從而實現不重複消費(推薦使用 redis)。
④優先級隊列
優先級隊列,也就是具有高優先級的隊列,優先級高的消息具備優先被消費的特權。通過隊列的 x-max-priority 參數設置隊列的最大優先級,之後在發送消息時通過 priority 屬性再設置當前消息的優先級。優先級應在 0 和 255 之間,推薦 1 ~ 10。
-
優先級默認最低爲 0,最高爲隊列設置的最大優先級;
-
對於單條消息來談優先級是沒有什麼意義的。假如消費者的消費速度大於生產者的速度且 Broker 中沒有消息堆積的情況下,對發送的消息設置優先級就沒有什麼意義,因爲生產者剛發完一個消息就被消費者消費了,相當於 Broker 中至多隻有一條消息。
⑤惰性隊列
惰性隊列會盡可能地將消息存入磁盤中,而在消費者消費消息時纔會被加載到內存中,它支持更多的消息存儲。
隊列具備兩種模式:default 和 lazy。默認的爲 default 模式,在隊列聲明的時候可以通過 “x-queue-mode” 參數來設置隊列的模式,取值爲 “default” 和“lazy”。
來源:
https://www.toutiao.com/article/7093159482301481479/?log_from=bf921adb3456e_1659403348624
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/XSMeiM5J5GMfyoedVcKG-w