消息隊列中間件重要嗎?面試必問問題之一,你說重不重要。我有時會問同事,為啥你用 RabbitMQ,不用 Kafka,或者 RocketMQ 呢,他給我的回答 “因為公司用的就是這個,大家都這么用”,如果你去面試,直接就被 Pass,今天這篇文章,告訴你如何回答。
這篇文章,我重點突出消息隊列選型,弱化每種隊列內部的實現細節,精華提煉,可讀性更強!
常用的消息隊列主要這 4 種,分別為 Kafka、RabbitMQ、RocketMQ 和 ActiveMQ,主要介紹前三,不BB,上思維導圖!
消息隊列基礎
什么是消息隊列?
消息隊列是在消息的傳輸過程中保存消息的容器,用于接收消息并以文件的方式存儲,一個消息隊列可以被一個也可以被多個消費者消費,包含以下 3 元素:
Producer:消息生產者,負責產生和發送消息到 Broker;
Broker:消息處理中心,負責消息存儲、確認、重試等,一般其中會包含多個 Queue;
Consumer:消息消費者,負責從 Broker 中獲取消息,并進行相應處理。
消息隊列模式
點對點模式:多個生產者可以向同一個消息隊列發送消息,一個具體的消息只能由一個消費者消費。
發布/訂閱模式:單個消息可以被多個訂閱者并發的獲取和處理。
消息隊列應用場景
應用解耦 :消息隊列減少了服務之間的耦合性,不同的服務可以通過消息隊列進行通信,而不用關心彼此的實現細節。
異步處理 :消息隊列本身是異步的,它允許接收者在消息發送很長時間后再取回消息。
流量削鋒 :當上下游系統處理能力存在差距的時候,利用消息隊列做一個通用的”載體”,在下游有能力處理的時候,再進行分發與處理。
日志處理 :日志處理是指將消息隊列用在日志處理中,比如 Kafka 的應用,解決大量日志傳輸的問題。
消息通訊 :消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊,比如實現點對點消息隊列,或者聊天室等。
消息廣播 :如果沒有消息隊列,每當一個新的業務方接入,我們都要接入一次新接口。有了消息隊列,我們只需要關心消息是否送達了隊列,至于誰希望訂閱,是下游的事情,無疑極大地減少了開發和聯調的工作量。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
項目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
常用消息隊列
由于官方社區現在對 ActiveMQ 5.x 維護越來越少,較少在大規模吞吐的場景中使用,所以我們主要講解 Kafka、RabbitMQ 和 RocketMQ。
Kafka
Apache Kafka 最初由 LinkedIn 公司基于獨特的設計實現為一個分布式的提交日志系統,之后成為 Apache 項目的一部分,號稱大數據的殺手锏,在數據采集、傳輸、存儲的過程中發揮著舉足輕重的作用。
它是一個分布式的,支持多分區、多副本,基于 Zookeeper 的分布式消息流平臺 ,它同時也是一款開源的基于發布訂閱模式的消息引擎系統。
重要概念
主題(Topic) :消息的種類稱為主題,可以說一個主題代表了一類消息,相當于是對消息進行分類,主題就像是數據庫中的表。
分區(partition) :主題可以被分為若干個分區,同一個主題中的分區可以不在一個機器上,有可能會部署在多個機器上,由此來實現 kafka 的伸縮性。
批次 :為了提高效率, 消息會分批次寫入 Kafka,批次就代指的是一組消息。
消費者群組(Consumer Group) :消費者群組指的就是由一個或多個消費者組成的群體。
Broker : 一個獨立的 Kafka 服務器就被稱為 broker,broker 接收來自生產者的消息,為消息設置偏移量,并提交消息到磁盤保存。
Broker 集群 :broker 集群由一個或多個 broker 組成。
重平衡(Rebalance) :消費者組內某個消費者實例掛掉后,其他消費者實例自動重新分配訂閱主題分區的過程。
Kafka 架構
一個典型的 Kafka 集群中包含 Producer、broker、Consumer Group、Zookeeper 集群。
Kafka 通過 Zookeeper 管理集群配置,選舉 leader,以及在 Consumer Group 發生變化時進行 rebalance。Producer 使用 push 模式將消息發布到 broker,Consumer 使用 pull 模式從 broker 訂閱并消費消息。
Kafka 工作原理
消息經過序列化后,通過不同的分區策略,找到對應的分區。
相同主題和分區的消息,會被存放在同一個批次里 ,然后由一個獨立的線程負責把它們發到 Kafka Broker 上。
分區的策略包括順序輪詢、隨機輪詢和 key hash 這 3 種方式,那什么是分區呢?
分區是 Kafka 讀寫數據的最小粒度,比如主題 A 有 15 條消息,有 5 個分區,如果采用順序輪詢的方式,15 條消息會順序分配給這 5 個分區,后續消費的時候,也是按照分區粒度消費。
由于分區可以部署在多個不同的機器上,所以可以通過分區實現 Kafka 的伸縮性,比如主題 A 的 5 個分區,分別部署在 5 臺機器上,如果下線一臺,分區就變為 4。
Kafka 消費是通過消費群組完成,同一個消費者群組,一個消費者可以消費多個分區,但是一個分區,只能被一個消費者消費。
如果消費者增加,會觸發 Rebalance,也就是分區和消費者需要重新配對 。
不同的消費群組互不干涉 ,比如下圖的 2 個消費群組,可以分別消費這 4 個分區的消息,互不影響。
RocketMQ
RocketMQ 是阿里開源的消息中間件,它是純 Java 開發,具有高性能、高可靠、高實時、適合大規模分布式系統應用的特點。
RocketMQ 思路起源于 Kafka,但并不是 Kafka 的一個 Copy,它對消息的可靠傳輸及事務性做了優化 ,目前在阿里集團被廣泛應用于交易、充值、流計算、消息推送、日志流式處理、binlog 分發等場景。
重要概念
Name 服務器(NameServer) :充當注冊中心,類似 Kafka 中的 Zookeeper。
Broker : 一個獨立的 RocketMQ 服務器就被稱為 broker,broker 接收來自生產者的消息,為消息設置偏移量。
主題(Topic) :消息的第一級類型,一條消息必須有一個 Topic。
子主題(Tag) :消息的第二級類型,同一業務模塊不同目的的消息就可以用相同 Topic 和不同的 Tag 來標識。
分組(Group) :一個組可以訂閱多個 Topic,包括生產者組(Producer Group)和消費者組(Consumer Group)。
隊列(Queue) :可以類比 Kafka 的分區 Partition。
RocketMQ 工作原理
RockerMQ 中的消息模型就是按照主題模型所實現的,包括 Producer Group、Topic、Consumer Group 三個角色。
為了提高并發能力,一個 Topic 包含多個 Queue ,生產者組根據主題將消息放入對應的 Topic,下圖是采用輪詢的方式找到里面的 Queue。
RockerMQ 中的消費群組和 Queue,可以類比 Kafka 中的消費群組和 Partition:不同的消費者組互不干擾,一個 Queue 只能被一個消費者消費,一個消費者可以消費多個 Queue。
消費 Queue 的過程中,通過偏移量記錄消費的位置。
RocketMQ 架構
RocketMQ 技術架構中有四大角色 NameServer、Broker、Producer 和 Consumer,下面主要介紹 Broker。
Broker 用于存放 Queue,一個 Broker 可以配置多個 Topic,一個 Topic 中存在多個 Queue。
如果某個 Topic 消息量很大,應該給它多配置幾個 Queue,并且盡量多分布在不同 broker 上,以減輕某個 broker 的壓力。Topic 消息量都比較均勻的情況下,如果某個 broker 上的隊列越多,則該 broker 壓力越大。
簡單提一下,Broker 通過集群部署,并且提供了 master/slave 的結構,slave 定時從 master 同步數據(同步刷盤或者異步刷盤),如果 master 宕機,則 slave 提供消費服務,但是不能寫入消息。
看到這里,大家應該可以發現,RocketMQ 的設計和 Kafka 真的很像!
RabbitMQ
RabbitMQ 2007 年發布,是使用 Erlang 語言開發的開源消息隊列系統,基于 AMQP 協議來實現。
AMQP 的主要特征是面向消息、隊列、路由、可靠性、安全。AMQP 協議更多用在企業系統內,對數據一致性、穩定性和可靠性要求很高的場景,對性能和吞吐量的要求還在其次。
重要概念
信道(Channel) :消息讀寫等操作在信道中進行,客戶端可以建立多個信道,每個信道代表一個會話任務。
交換器(Exchange) :接收消息,按照路由規則將消息路由到一個或者多個隊列;如果路由不到,或者返回給生產者,或者直接丟棄。
路由鍵(RoutingKey) :生產者將消息發送給交換器的時候,會發送一個 RoutingKey,用來指定路由規則,這樣交換器就知道把消息發送到哪個隊列。
綁定(Binding) :交換器和消息隊列之間的虛擬連接,綁定中可以包含一個或者多個 RoutingKey。
RabbitMQ 工作原理
AMQP 協議模型由三部分組成:生產者、消費者和服務端,執行流程如下:
生產者是連接到 Server,建立一個連接,開啟一個信道。
生產者聲明交換器和隊列,設置相關屬性,并通過路由鍵將交換器和隊列進行綁定。
消費者也需要進行建立連接,開啟信道等操作,便于接收消息。
生產者發送消息,發送到服務端中的虛擬主機。
虛擬主機中的交換器根據路由鍵選擇路由規則,發送到不同的消息隊列中。
訂閱了消息隊列的消費者就可以獲取到消息,進行消費。
常用交換器
RabbitMQ 常用的交換器類型有 direct、topic、fanout、headers 四種。
具體的使用方法,可以參考官網:
官網入口:https://www.rabbitmq.com/getstarted.html
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
項目地址:https://gitee.com/zhijiantianya/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
消息隊列對比&選型
消息隊列對比
Kafka
優點:
高吞吐、低延遲 :Kafka 最大的特點就是收發消息非常快,Kafka 每秒可以處理幾十萬條消息,它的最低延遲只有幾毫秒;
高伸縮性 :每個主題(topic)包含多個分區(partition),主題中的分區可以分布在不同的主機(broker)中;
高穩定性 :Kafka 是分布式的,一個數據多個副本,某個節點宕機,Kafka 集群能夠正常工作;
持久性、可靠性、可回溯 :Kafka 能夠允許數據的持久化存儲,消息被持久化到磁盤,并支持數據備份防止數據丟失,支持消息回溯;
消息有序:通過控制能夠保證所有消息被消費且僅被消費一次;
有優秀的第三方 Kafka Web 管理界面 Kafka-Manager,在日志領域比較成熟,被多家公司和多個開源項目使用。
缺點:
Kafka 單機超過 64 個隊列/分區,Load 會發生明顯的飆高現象,隊列越多,load 越高,發送消息響應時間變長;
不支持消息路由,不支持延遲發送,不支持消息重試;
社區更新較慢。
RocketMQ
優點:
高吞吐 :借鑒 Kafka 的設計,單一隊列百萬消息的堆積能力;
高伸縮性 :靈活的分布式橫向擴展部署架構,整體架構其實和 kafka 很像;
高容錯性 :通過ACK機制,保證消息一定能正常消費;
持久化、可回溯 :消息可以持久化到磁盤中,支持消息回溯;
消息有序:在一個隊列中可靠的先進先出(FIFO)和嚴格的順序傳遞;
支持發布/訂閱和點對點消息模型,支持拉、推兩種消息模式;
提供 docker 鏡像用于隔離測試和云集群部署,提供配置、指標和監控等功能豐富的 Dashboard。
缺點:
不支持消息路由,支持的客戶端語言不多,目前是 java 及 c++,其中 c++ 不成熟 ;
部分支持消息有序:需要將同一類的消息 hash 到同一個隊列 Queue 中,才能支持消息的順序,如果同一類消息散落到不同的 Queue中,就不能支持消息的順序。
社區活躍度一般。
RabbitMQ
優點:
支持幾乎所有最受歡迎的編程語言 :Java,C,C ++,C#,Ruby,Perl,Python,PHP等等;
支持消息路由 :RabbitMQ 可以通過不同的交換器支持不同種類的消息路由;
消息時序 :通過延時隊列,可以指定消息的延時時間,過期時間TTL等;
支持容錯處理:通過交付重試和死信交換器(DLX)來處理消息處理故障;
提供了一個易用的用戶界面,使得用戶可以監控和管理消息 Broker;
社區活躍度高。
缺點:
Erlang 開發,很難去看懂源碼,不利于做二次開發和維護 ,基本只能依賴于開源社區的快速維護和修復 bug;
RabbitMQ 吞吐量會低一些 ,這是因為他做的實現機制比較重;
不支持消息有序、持久化不好、不支持消息回溯、伸縮性一般。
消息隊列選型
Kafka:追求高吞吐量,一開始的目的就是用于日志收集和傳輸,適合產生大量數據的互聯網服務的數據收集業務 ,大型公司建議可以選用,如果有日志采集功能,肯定是首選 kafka。
RocketMQ:天生為金融互聯網領域而生,對于可靠性要求很高的場景 ,尤其是電商里面的訂單扣款,以及業務削峰,在大量交易涌入時,后端可能無法及時處理的情況。RocketMQ 在穩定性上可能更值得信賴,這些業務場景在阿里雙 11 已經經歷了多次考驗,如果你的業務有上述并發場景,建議可以選擇 RocketMQ。
RabbitMQ:結合 erlang 語言本身的并發優勢,性能較好,社區活躍度也比較高,但是不利于做二次開發和維護,不過 RabbitMQ 的社區十分活躍,可以解決開發過程中遇到的 bug。如果你的數據量沒有那么大,小公司優先選擇功能比較完備的 RabbitMQ。
審核編輯:劉清
-
服務器
+關注
關注
12文章
9029瀏覽量
85207 -
交換器
+關注
關注
2文章
90瀏覽量
16527 -
虛擬機
+關注
關注
1文章
908瀏覽量
28109 -
AMQP
+關注
關注
0文章
6瀏覽量
2553
原文標題:消息隊列原理和選型:Kafka、RocketMQ 、RabbitMQ 和 ActiveMQ
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論