RabbitMQ 應(yīng)知應(yīng)會的面試題
RabbitMQ 相關(guān)問題如何解決
MQ 是什么?
MQ(Message Queue)消息隊列
用隊列機制來實現(xiàn)軟件之間的通信,消費者可以到指定隊列拉取消息,或者訂閱相應(yīng)的隊列,由MQ服務(wù)端給其推送消息
什么是隊列?
是一種數(shù)據(jù)結(jié)構(gòu),遵循 FIFO (先進先出)原則
憑啥要使用 MQ , MQ 有啥優(yōu)勢?
異步通信
將以前也不中不必要的同步操作,優(yōu)化成異步操作,提高性能
業(yè)務(wù)解耦
將原有A模塊直接調(diào)用B模塊的接口,優(yōu)化成,A模塊的請求給到MQ,A模塊的事情就做完了
MQ會主動推給B模塊,或者B模塊自己來拉
流量削峰
當(dāng)某一時間大量的流量打到服務(wù)器上,服務(wù)器一時間無法承受,會宕機
這個時候,若請求都是從消息隊列里面出來,則能夠保證這種大流量的情況下,服務(wù)器仍然能夠有序的穩(wěn)定的處理請求
MQ 有啥劣勢呢?
系統(tǒng)可用性降低,對外部有依賴了
需要考慮 MQ 消息丟失,重復(fù)消費的問題
需要花費精力保證消息的順序性,一致性
常用 MQ 性能對比
| ActiveMQ | RabbitMQ | RocketMQ | Kafka | |
|---|---|---|---|---|
| 開發(fā)語言 | java | erlang | java | scala |
| 單機吞吐量 | 萬級 | 萬級 | 十萬級 | 十萬級 |
| 時效性 | ms級 | us級 | ms級 | ms級以內(nèi) |
| 可用性 | 高 主從架構(gòu) | 高 主從架構(gòu) | 非常高 分布式架構(gòu) | 非常高 分布式架構(gòu) |
| 消息可靠性 | 較低概率丟失消息 | 基本不丟 | 可以做到基本不丟 | 可以做到基本不丟 |
| 功能支持 | 支持功能全 | 性能好 延時低 并發(fā)能力強 | MQ 功能較完善 支持分布式,擴展性好 | 主要用于大數(shù)據(jù)和日志采集 |
MQ 如何避免消息堆積
提高消費速率(集群的方式)
消費者批量獲取消息進行消費
MQ 如何避免消費者重復(fù)消費(冪等性問題)
全局ID(增加標(biāo)志位) + 保證業(yè)務(wù)一致性
MQ 如何保證消息不丟失
消息確認機制
持久化
消息 ACK
MQ 如何保證消息順序一致性
綁定同一個消費者和隊列
MQ 推與拉取架構(gòu)模型是怎么樣的?
MQ 服務(wù)器與消費者建立長連接后,MQ 服務(wù)器會主動推數(shù)據(jù)給到消費者
當(dāng)消費者第一次啟動的時候,會去找MQ 服務(wù)器拉數(shù)據(jù)
mq有哪些消費模式
推模式 注冊一個消費者后,RabbitMQ會在消息可用時,自動將消息進行推送給消費者。這種方式效率最高最及時。
拉模式 屬于一種輪詢模型,發(fā)送一次get請求,獲得一個消息。如果此時RabbitMQ中沒有消息,會獲得一個表示空的回復(fù)。
自動確認
消費者消費消息的時候,將自動向RabbitMQ進行確認。
手動確認
消費者消費消息的時候,手動調(diào)用相應(yīng)函數(shù)進行ack 應(yīng)答
qos預(yù)取模式
在確認消息被接收之前,消費者可以預(yù)先要求接收一定數(shù)量的消息,在處理完一定數(shù)量的消息后,批量進行確認
當(dāng)然,如果消費者應(yīng)用程序在確認消息之前崩潰,則所有未確認的消息將被重新發(fā)送給其他消費者
RabbitMQ 中既然有了connections 為什么還要有 channel?
connection 是什么
connection 是 生產(chǎn)者或消費者與 RabbitMQ Broker 建立的連接,是一個TCP連接
一旦 TCP 連接建立起來,客戶端緊接著可以創(chuàng)建一個 AMQP 信道(Channel),每個信道都會被指派一個唯一的 ID
信道是建立在 Connection 之上的虛擬連接,多個信道復(fù)用一個TCP連接,可以減少性能開銷,同時也便于管理
因為一個應(yīng)用需要向RabbitMQ 中生成或者消費消息的話,都要建一個TCP連接,TCP連接開銷非常大,如果遇到使用高峰,性能瓶頸也隨之顯現(xiàn)
信道復(fù)用連接優(yōu)勢:
復(fù)用TCP連接,減少性能開銷,便于管理
RabbitMQ 保障每一個信道的私密性

當(dāng)每個信道的流量不是很大時,復(fù)用單一的 Connection 可以在產(chǎn)生性能瓶頸的情況下有效地節(jié)省 TCP 連接資源
信道本身的流量很大時,這時候多個信道復(fù)用一個 Connection 就會產(chǎn)生性能瓶頸,進而使整體的流量被限制了,此時就需要開辟多個 Connection,將這些信道均攤到這些 Connection 中
RabbitMQ 的作用
削峰填谷
生產(chǎn)者和消費者業(yè)務(wù)解耦
服務(wù)間異步通信
定時任務(wù)
順序消費
為什么選擇 RabbitMQ
現(xiàn)在的市面上有很多 MQ 可以選擇,比如 ActiveMQ、ZeroMQ、Appche Qpid為什么要選擇 RabbitMQ?
除了 Qpid,RabbitMQ 是唯一一個實現(xiàn)了 AMQP 標(biāo)準的消息服務(wù)器
可靠性,RabbitMQ 的持久化支持,保證了消息的穩(wěn)定性
高并發(fā),RabbitMQ 使用了 Erlang 開發(fā)語言,Erlang 是為電話交換機開發(fā)的語言,天生自帶高并發(fā)光環(huán),和高可用特性
集群部署簡單,正是應(yīng)為 Erlang 使得 RabbitMQ 集群部署變的超級簡單
社區(qū)活躍度高,根據(jù)網(wǎng)上資料來看,RabbitMQ 也是首選
RabbitMQ 的特點是什么?
可靠
RabbitMQ 使用 如持久化、傳輸確認及發(fā)布確認等機制來保證可靠性
靈活的路由
通過交換器來路由消息
對于典型的路由功能, RabbitMQ 己經(jīng)提供了一些內(nèi)置的交換器來實現(xiàn)
針對更復(fù)雜的路由功能,可以將多個 交換器綁定在一起,這個就需要通過插件來實現(xiàn)了
擴展性
多個 RabbitMQ 節(jié)點可以組成一個集群,也可以根據(jù)實際業(yè)務(wù)情況動態(tài)地擴展集群中節(jié)點
高可用性
隊列可以在集群中的機器上設(shè)置鏡像,使得在部分節(jié)點出現(xiàn)問題的情況下隊列仍然可用
支持的協(xié)議多
RabbitMQ 除了原生支持 AMQP 協(xié)議,還支持 STOMP, MQTT等多種消息中間件協(xié)議
多語言客戶端
RabbitMQ 幾乎支持所有常用語言,比如 GO、 Java、 Python、 Ruby、 PHP等
WEB 管理界面
RabbitMQ 提供了一個易用的用戶界面,使得用戶可以監(jiān)控和管理消息、集群中的節(jié)點等
命令插件機制
RabbitMQ 提供了許多插件 , 以實現(xiàn)從多方面進行擴展,當(dāng)然也可以編寫自己的插件
生產(chǎn)者Producer和消費者Consumer 有哪些知識點?
生產(chǎn)者
消息生產(chǎn)者,投遞消息
消息一般包含兩個部分:消息體(
payload)和標(biāo)簽(Label)
消費者
消費消息,接收消息
消費者連接到 RabbitMQ 服務(wù)器,并訂閱到隊列
消費消息時只消費消息體,丟棄標(biāo)簽
RabbitMQ 消息持久化中的坑
默認情況下重啟服務(wù)器會導(dǎo)致消息丟失,我們?nèi)绾伪WC重啟 RabbitMQ 不丟失數(shù)據(jù)?
那就是做持久化,持久化需要滿足如下三個條件才可以恢復(fù) RabbitMQ 的數(shù)據(jù)
投遞消息的時候 durable 設(shè)置為 true,消息持久化
消息已經(jīng)到達持久化交換器上
消息已經(jīng)到達持久化的隊列上
持久化的工作原理
Rabbit 會將持久化消息寫入磁盤上的持久化日志文件,等消息被消費之后,Rabbit 會把這條消息標(biāo)識為等待垃圾回收
持久化的優(yōu)缺點
優(yōu)點
數(shù)據(jù)持久化,數(shù)據(jù)不丟失
缺點
對性能有影響,寫硬盤比寫內(nèi)存性能低,從而降低服務(wù)的吞吐量
RabbitMQ ACK 應(yīng)答機制
ACK 應(yīng)答分為手動和自動,各有優(yōu)劣
如果消息不太重要,丟失也沒有影響,那么自動 ACK 會比較方便
如果消息非常重要,不容丟失。那么最好在消費完成后手動 ACK
否則接收消息后就自動 ACK,RabbitMQ 就會把消息從隊列中刪除。若此時消費者宕機或處理業(yè)務(wù)失敗,那么消息就丟失了
ACK 機制的開發(fā)注意事項
如果忘記了 ACK,那么后果很嚴重
當(dāng) Consumer 退出時候,Message 會一直重新分發(fā)。然后 RabbitMQ 會占用越來越多的內(nèi)容,由于 RabbitMQ 會長時間運行,這個” 內(nèi)存泄漏” 是致命的
為什么需要限流,消費者流量控制
某一時刻,生產(chǎn)者在 RabbitMQ 隊列中堆積了很多消息,此時有一個消費者啟動,大量的消息會推送到消費者上面,這種瞬時大流量會把消費者打掛
生產(chǎn)者和消費者效率不平衡的情況,會導(dǎo)致消費者端性能下降,服務(wù)端卡頓或者崩潰
RabbitMQ 的組成
生產(chǎn)者 producer
消費者 consumer
交換機 exchange
用于接受、分配消息
消息 message
隊列 queue
用于存儲生產(chǎn)者的消息
信道 channel AMQP
消息推送使用的通道
連接 connections
生成者或者消費者與Rabbit 建立的TCP 連接
路由鍵 routingKey
用于把生成者的數(shù)據(jù)分配到交換器上
綁定鍵 BindingKey
用于把交換器的消息綁定到隊列上
連接管理器 ConnectionFactory
應(yīng)用程序與 Rabbit 之間建立連接的管理器,程序代碼中使用
VHost
vhost 可以理解為虛擬 broker,即虛擬機
其內(nèi)部均含有獨立的 queue、exchange 和 binding 等
擁有獨立的權(quán)限系統(tǒng),做到資源隔離,資源高效利用
RabbitMQ 的六種模式
single
簡單的生產(chǎn)者生產(chǎn)消息,放入隊列,消費者消費消息
work
當(dāng)生產(chǎn)者生產(chǎn)消息的速度大于消費者消費的速度,就要考慮用 work 工作模式,這樣能提高處理速度提高負載
work 模式與 single 模式類似, 只是work 模式比 single 模式多了一些消費者
publish
應(yīng)用場景:簡單消息隊列的使用,一個生產(chǎn)者一個消費者
routing
消息生產(chǎn)者將消息發(fā)送給交換機按照路由判斷,路由是字符串(info) 當(dāng)前產(chǎn)生的消息攜帶路由字符(對象的方法),交換機根據(jù)路由的key
只能匹配上路由key對應(yīng)的消息隊列,對應(yīng)的消費者才能消費消息
topic
話題模式,一個消息被多個消費者獲取,消息的目標(biāo) queue 可用 BindingKey 以通配符
rpc
通過遠程過程調(diào)用的方式實現(xiàn)
存儲機制
持久化消息
持久化的消息在到達隊列時就被寫入磁盤,持久化的消息也會在內(nèi)存中保存一份備份,這樣可以提高一定的性能,當(dāng)內(nèi)存吃緊的時候會從內(nèi)存中清除
非持久化消息
一般只保存在內(nèi)存中,在內(nèi)存吃緊的時候會被換入到磁盤中,以節(jié)省內(nèi)存空間
RabbitMQ中消息可能有的幾種狀態(tài)
alpha
消息內(nèi)容(包括消息體、屬性和 headers) 和消息索引都存儲在內(nèi)存中
beta
消息內(nèi)容保存在磁盤中,消息索引保存在內(nèi)存中
gamma
消息內(nèi)容保存在磁盤中,消息索引在磁盤和內(nèi)存中都有
delta
消息內(nèi)容和索引都在磁盤中
RabbitMQ 的隊列結(jié)構(gòu)?
rabbit_amqqueue_process
負責(zé)協(xié)議相關(guān)的消息處理,即接收生產(chǎn)者發(fā)布的消息、向消費者交付消息、處理消息的確認等
backing_queue
是消息存儲的具體形式和引擎,并向 rabbit_amqqueue_process 提供相關(guān)的接口以供調(diào)用
交換器無法根據(jù)自身類型和路由鍵找到符合條件隊列時,會如何處理?
我們對交換機設(shè)置參數(shù)的時候,有一個標(biāo)志叫做 mandatory
當(dāng)mandatory標(biāo)志位設(shè)置為true時
如果exchange根據(jù)自身類型和消息routingKey無法找到一個合適的queue存儲消息,那么broker就會調(diào)用basic.return方法將消息返還給生產(chǎn)者
當(dāng)mandatory設(shè)置為false時
前置條件和上述保持一致,此時 broker會直接將消息丟棄
如何保證消息可靠性嘞?
消息從生產(chǎn)者到 MQ
由事務(wù)機制,確認機制 來保障
MQ 自身可靠性
由持久化、集群、普通模式、鏡像模式來保證
MQ 消息到消費者
由basicAck機制、死信隊列、消息補償?shù)葯C制來保證
集群中的節(jié)點類型有哪些?
內(nèi)存節(jié)點
ram,將變更寫入內(nèi)存。
磁盤節(jié)點
disc,磁盤寫入操作
RabbitMQ中 要求最少有一個磁盤節(jié)點
如何保證 RabbitMQ 消息隊列的高可用?
RabbitMQ中有三種模式來保證:
單機模式
一般是本地啟動,自己學(xué)習(xí)和測試使用,不會用在生產(chǎn)環(huán)境上
普通集群模式
在多臺機器上啟動多個 RabbitMQ 實例,每個機器啟動一個
鏡像集群模式
RabbitMQ的高可用模式
跟普通集群模式不一樣的是,創(chuàng)建的 queue,無論元數(shù)據(jù)(元數(shù)據(jù)指 RabbitMQ 的配置數(shù)據(jù))還是 queue 里的消息都會存在于多個實例上,
然后每次寫消息到 queue 的時候,都會自動把消息到多個實例的 queue 里進行消息同步
參考資料:
RabbitMQ Tutorials
歡迎點贊,關(guān)注,收藏
朋友們,你的支持和鼓勵,是我堅持分享,提高質(zhì)量的動力

好了,本次就到這里
技術(shù)是開放的,我們的心態(tài),更應(yīng)是開放的。擁抱變化,向陽而生,努力向前行。
作者:小魔童哪吒
鏈接:https://juejin.cn/post/6991610913354678285
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
