消息隊列與RabbitMQ


本文借鑑了新手也能看懂,消息隊列其實很簡單中有關消息隊列的部分內容

一.消息隊列

消息隊列是一個存放消息的容器,當我們需要使用消息的時候可以取出消息供自己使用。分佈式系統中經常要使用到消息隊列,使用消息隊列主要是爲了達成兩個目的,第一點是通過異步處理提高系統性能,消息隊列有削峯、減少響應所需時間的功能;第二點是降低系統耦合性。

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

在這裏插入圖片描述
如上圖,在不使用消息隊列服務器的時候,用戶請求後一直要等到數據庫寫入完成後才能響應,因此用戶必須要等待很長時間,服務器的負載也會因此飆升。
但是在使用消息隊列之後,用戶的請求數據發送給消息隊列之後立刻返回響應,然後數據庫再從消息隊列中讀取數據寫入數據庫,這樣用戶請求處理的過程就變成了一個異步的過程。由於消息隊列服務器處理速度快於數據庫(消息隊列也比數據庫有更好的伸縮性),因此響應速度得到大幅改善。

通過以上分析我們可以得出消息隊列具有很好的削峯作用的功能——即通過異步處理,將短時間高併發產生的事務消息存儲在消息隊列中,從而削平高峯期的併發事務。 舉例:在電子商務一些秒殺、促銷活動中,合理使用消息隊列可以有效抵禦促銷活動剛開始大量訂單湧入對系統的衝擊。如下圖所示:

在這裏插入圖片描述

1.2 降低系統耦合性

在不使用消息中間件的場合下,如果業務邏輯比較複雜,那麼業務關係之間的關係就會非常混亂,難以管理,複用性也非常差
在這裏插入圖片描述加入消息中間件以後,生產者統一到消息隊列中發佈服務,消費者訂閱服務,服務之間的調用關係可以在消息隊列中非常清晰的看到,當系統的某一個模塊需要升級或者有新的功能模塊需要加入進來都會非常方便
在這裏插入圖片描述

1.3 常用的幾種消息隊列及其比較

ActiveMQ

社區算是比較成熟,但是較目前來說,ActiveMQ 的性能比較差,而且版本迭代很慢,不推薦使用。

RabbitMQ

在吞吐量方面雖然稍遜於 Kafka 和 RocketMQ ,但是由於它基於 erlang 開發,所以併發能力很強,性能極其好,延時很低,達到微秒級。但是也因爲 RabbitMQ 基於 erlang 開發,所以國內很少有公司有實力做erlang源碼級別的研究和定製。如果業務場景對併發量要求不是太高(十萬級、百萬級),那這四種消息隊列中,RabbitMQ 一定是你的首選。

kafka

特點其實很明顯,就是僅僅提供較少的核心功能,但是提供超高的吞吐量,ms 級的延遲,極高的可用性以及可靠性,而且分佈式可以任意擴展。同時 kafka 最好是支撐較少的 topic 數量即可,保證其超高吞吐量。kafka 唯一的一點劣勢是有可能消息重複消費,那麼對數據準確性會造成極其輕微的影響,在大數據領域中以及日誌採集中,這點輕微影響可以忽略,這個特性天然適合大數據實時計算以及日誌收集。

二.RabbitMQ

RabbitMQ是一個瑞典通訊公司開發的軟件,基於 erlang 語言,由於最初被當做通信軟件設計和使用,所以它的併發能力很強,性能極其好,延時很低。非常適合用在對併發量要求不是太高的業務場合。
RabbitMQ有六種工作模式,下面我會一一介紹:
在這裏插入圖片描述

1.簡單隊列

RabbitMQ是一個消息代理。它的工作就是接收和轉發消息。你可以把它想像成一個郵局:你把信件放入郵箱,郵遞員就會把信件投遞到你的收件人處。在這個比喻中,RabbitMQ就扮演着郵箱、郵局以及郵遞員的角色。

RabbitMQ和郵局的主要區別在於,它不是處理紙張,而是接收、存儲和發送消息(message)這種二進制數據。

下圖中,“P”代表生產者,“C”代表消費者,中間的紅色盒子代表爲消費者保留的消息緩衝區,也就是消息隊列。這是一個最簡單的RabbitMQ的例子
在這裏插入圖片描述

2.工作隊列

工作隊列(又稱:任務隊列——Task Queues)是爲了避免等待一些佔用大量資源、時間的操作。當把任務(Task)當作消息發送到隊列中,一個運行在後臺的工作者(worker)進程就會取出任務然後處理。當運行多個工作者(workers),任務就會在它們之間共享,這幾個工作者會一起處理這些任務。

在這裏插入圖片描述

3.發佈/訂閱

相比於之前的工作隊列隊列模式,發佈/訂閱多了一個交換機(exchange)。

發佈者(producer)只需要把消息發送給一個交換機。交換機一邊從發佈者方接收消息,一邊把消息推送到隊列。交換機必須知道如何處理它接收到的消息,是應該推送到指定的隊列還是是多個隊列,或者是直接忽略消息。這些規則是通過交換機類型(exchange type)來定義的。

交換器和隊列之間的聯繫我們稱之爲綁定(binding)。如下圖所示:
在這裏插入圖片描述

發佈/訂閱使用的交換機的類型是扇型交換機(fanout exchange),扇型交換機會把消息轉發給所有隊列。

發佈/訂閱模式下,消費者不用在將消息一個一個的發送到所有隊列中,消費者只需要將消息發送給交換機,交換機就會將消息自動轉發給所有生產者。

在這裏插入圖片描述

4.路由

交換機是由很多種類型的,扇型交換機(fanout exchange)沒有足夠的靈活性 —— 它能做的僅僅是廣播,將消息發給所有隊列。直連交換機(direct exchange)有路由的功能 —— 交換機將會對綁定鍵(binding key)和路由鍵(routing key)進行精確匹配,從而確定消息該分發到哪個隊列。

在這裏插入圖片描述

5.主題交換機

主題交換機(topic exchange)相比於扇型交換機和直連交換機來說,多了一個規則匹配的功能,通過“#”和“.”兩個符號組成的規則來匹配路由鍵(routing key),“#”可以匹配多個單詞,“.”只能匹配一個單詞。

如下圖所示,三個綁定鍵(binding key)的匹配規則分別是“*.orange.*”“*.*.rabbit ”“lazy.#”,則quick.orange.rabbit會被髮送到C2,lazy.orange.elephant會被髮送給C1,關於匹配規則的更詳細的介紹,可以看這篇文章:RabbitMQ主題交換機,這篇文章是對RabbitMQ官網內容的翻譯
在這裏插入圖片描述

主題交換機是很強大的,它可以表現出跟其他交換機類似的行爲,當一個隊列的綁定鍵爲 “#”(井號) 的時候,這個隊列將會無視消息的路由鍵,接收所有的消息。當 * (星號) 和 # (井號) 這兩個特殊字符都未在綁定鍵中出現的時候,此時主題交換機就擁有的直連交換機的行爲。

6.遠程調用過程RPC

現在遇到一個需求,將一個函數運行在遠程計算機上並且等待從那兒獲取結果,這種模式通常被稱爲遠程過程調用(Remote Procedure Call)或者RPC,處理這種場景以上的例子就不合適了。

這時就需要用到RabbitMQ的RPC模式了,在RabbitMQ的RPC模式中,RabbitMQ爲每個客戶端只建立一個獨立的回調隊列。這就帶來一個問題,當此隊列接收到一個響應的時候它無法辨別出這個響應是屬於哪個請求的。correlation_id 就是爲了解決這個問題而來的。我們給每個請求設置一個獨一無二的值。稍後,當我們從回調隊列中接收到一個消息的時候,我們就可以查看這條屬性從而將響應和請求匹配起來。如果我們接手到的消息的correlation_id是未知的,那就直接銷燬掉它,因爲它不屬於我們的任何一條請求。

在這裏插入圖片描述

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