我們一起來學RabbitMQ 五:RabbitMQ 應知應會的面試題

小魔童哪吒發表於2021-10-15

MQ 是什麼?

MQ(Message Queue)訊息佇列

用佇列機制來實現軟體之間的通訊,消費者可以到指定佇列拉取訊息,或者訂閱相應的佇列,由MQ服務端給其推送訊息

什麼是佇列?

是一種資料結構,遵循 FIFO (先進先出)原則

憑啥要使用 MQ , MQ 有啥優勢?

  • 非同步通訊

將以前也不中不必要的同步操作,優化成非同步操作,提高效能

  • 業務解耦

將原有A模組直接呼叫B模組的介面,優化成,A模組的請求給到MQ,A模組的事情就做完了

MQ會主動推給B模組,或者B模組自己來拉

  • 流量削峰

當某一時間大量的流量打到伺服器上,伺服器一時間無法承受,會當機

這個時候,若請求都是從訊息佇列裡面出來,則能夠保證這種大流量的情況下,伺服器仍然能夠有序的穩定的處理請求

MQ 有啥劣勢呢?

  • 系統可用性降低,對外部有依賴了
  • 需要考慮 MQ 訊息丟失,重複消費的問題
  • 需要花費精力保證訊息的順序性,一致性

常用 MQ 效能對比

ActiveMQ RabbitMQ RocketMQ Kafka
開發語言 java erlang java scala
單機吞吐量 萬級 萬級 十萬級 十萬級
時效性 ms級 us級 ms級 ms級以內
可用性
主從架構

主從架構
非常高
分散式架構
非常高
分散式架構
訊息可靠性 較低概率丟失訊息 基本不丟 可以做到基本不丟 可以做到基本不丟
功能支援 支援功能全 效能好
延時低
併發能力強
MQ 功能較完善
支援分散式,擴充套件性好
主要用於大資料和日誌採集

MQ 如何避免訊息堆積

  • 提高消費速率(叢集的方式)
  • 消費者批量獲取訊息進行消費

MQ 如何避免消費者重複消費(冪等性問題)

  • 全域性ID(增加標誌位) + 保證業務一致性

MQ 如何保證訊息不丟失

  • 訊息確認機制
  • 持久化
  • 訊息 ACK

MQ 如何保證訊息順序一致性

  • 繫結同一個消費者和佇列

MQ 推與拉取架構模型是怎麼樣的?

  • MQ 伺服器與消費者建立長連線後,MQ 伺服器會主動推資料給到消費者
  • 當消費者第一次啟動的時候,會去找MQ 伺服器拉資料

mq有哪些消費模式

  • 推模式
    註冊一個消費者後,RabbitMQ會在訊息可用時,自動將訊息進行推送給消費者。這種方式效率最高最及時。

  • 拉模式
    屬於一種輪詢模型,傳送一次get請求,獲得一個訊息。如果此時RabbitMQ中沒有訊息,會獲得一個表示空的回覆。

  • 自動確認

消費者消費訊息的時候,將自動向RabbitMQ進行確認。

  • 手動確認

消費者消費訊息的時候,手動呼叫相應函式進行ack 應答

  • qos預取模式

在確認訊息被接收之前,消費者可以預先要求接收一定數量的訊息,在處理完一定數量的訊息後,批量進行確認

當然,如果消費者應用程式在確認訊息之前崩潰,則所有未確認的訊息將被重新傳送給其他消費者

RabbitMQ 中既然有了connections 為什麼還要有 channel

connection 是什麼

connection 是 生產者或消費者與 RabbitMQ Broker 建立的連線,是一個TCP連線

一旦 TCP 連線建立起來,客戶端緊接著可以建立一個 AMQP 通道(Channel),每個通道都會被指派一個唯一的 ID

通道是建立在 Connection 之上的虛擬連線,多個通道複用一個TCP連線,可以減少效能開銷,同時也便於管理

因為一個應用需要向RabbitMQ 中生成或者消費訊息的話,都要建一個TCP連線,TCP連線開銷非常大,如果遇到使用高峰,效能瓶頸也隨之顯現

通道複用連線優勢:

  • 複用TCP連線,減少效能開銷,便於管理
  • RabbitMQ 保障每一個通道的私密性

當每個通道的流量不是很大時,複用單一的 Connection 可以在產生效能瓶頸的情況下有效地節省 TCP 連線資源

通道本身的流量很大時,這時候多個通道複用一個 Connection 就會產生效能瓶頸,進而使整體的流量被限制了,此時就需要開闢多個 Connection,將這些通道均攤到這些 Connection 中

RabbitMQ 的作用

  • 削峰填谷
  • 生產者和消費者業務解耦
  • 服務間非同步通訊
  • 定時任務
  • 順序消費

為什麼選擇 RabbitMQ

現在的市面上有很多 MQ 可以選擇,比如 ActiveMQ、ZeroMQ、Appche Qpid為什麼要選擇 RabbitMQ

  • 除了 Qpid,RabbitMQ 是唯一一個實現了 AMQP 標準的訊息伺服器
  • 可靠性,RabbitMQ 的持久化支援,保證了訊息的穩定性
  • 高併發,RabbitMQ 使用了 Erlang 開發語言,Erlang 是為電話交換機開發的語言,天生自帶高併發光環,和高可用特性
  • 叢集部署簡單,正是應為 Erlang 使得 RabbitMQ 叢集部署變的超級簡單
  • 社群活躍度高,根據網上資料來看,RabbitMQ 也是首選

RabbitMQ 的特點是什麼?

  • 可靠

    RabbitMQ 使用 如持久化、傳輸確認及釋出確認等機制來保證可靠性

  • 靈活的路由

通過交換器來路由訊息

對於典型的路由功能, RabbitMQ 己經提供了一些內建的交換器來實現

針對更復雜的路由功能,可以將多個 交換器繫結在一起,這個就需要通過外掛來實現了

  • 擴充套件性

多個 RabbitMQ 節點可以組成一個叢集,也可以根據實際業務情況動態地擴充套件叢集中節點

  • 高可用性

佇列可以在叢集中的機器上設定映象,使得在部分節點出現問題的情況下佇列仍然可用

  • 支援的協議多

RabbitMQ 除了原生支援 AMQP 協議,還支援 STOMP, MQTT等多種訊息中介軟體協議

  • 多語言客戶端

RabbitMQ 幾乎支援所有常用語言,比如 GO、 Java、 Python、 Ruby、 PHP等

  • WEB 管理介面

RabbitMQ 提供了一個易用的使用者介面,使得使用者可以監控和管理訊息、叢集中的節點等

  • 命令外掛機制

RabbitMQ 提供了許多外掛 , 以實現從多方面進行擴充套件,當然也可以編寫自己的外掛

生產者Producer和消費者Consumer 有哪些知識點?

生產者

  • 訊息生產者,投遞訊息
  • 訊息一般包含兩個部分:訊息體(payload)和標籤(Label)

消費者

  • 消費訊息,接收訊息

  • 消費者連線到 RabbitMQ 伺服器,並訂閱到佇列

    消費訊息時只消費訊息體,丟棄標籤

RabbitMQ 訊息持久化中的坑

預設情況下重啟伺服器會導致訊息丟失,我們如何保證重啟 RabbitMQ 不丟失資料?

那就是做持久化,持久化需要滿足如下三個條件才可以恢復 RabbitMQ 的資料

  • 投遞訊息的時候 durable 設定為 true,訊息持久化
  • 訊息已經到達持久化交換器上
  • 訊息已經到達持久化的佇列上

持久化的工作原理

Rabbit 會將持久化訊息寫入磁碟上的持久化日誌檔案,等訊息被消費之後,Rabbit 會把這條訊息標識為等待垃圾回收

持久化的優缺點

優點

  • 資料持久化,資料不丟失

缺點

  • 對效能有影響,寫硬碟比寫記憶體效能低,從而降低服務的吞吐量

RabbitMQ ACK 應答機制

ACK 應答分為手動和自動,各有優劣

  • 如果訊息不太重要,丟失也沒有影響,那麼自動 ACK 會比較方便

  • 如果訊息非常重要,不容丟失。那麼最好在消費完成後手動 ACK

    否則接收訊息後就自動 ACK,RabbitMQ 就會把訊息從佇列中刪除。若此時消費者當機或處理業務失敗,那麼訊息就丟失了

ACK 機制的開發注意事項

如果忘記了 ACK,那麼後果很嚴重

當 Consumer 退出時候,Message 會一直重新分發。然後 RabbitMQ 會佔用越來越多的內容,由於 RabbitMQ 會長時間執行,這個” 記憶體洩漏” 是致命的

為什麼需要限流,消費者流量控制

  • 某一時刻,生產者在 RabbitMQ 佇列中堆積了很多訊息,此時有一個消費者啟動,大量的訊息會推送到消費者上面,這種瞬時大流量會把消費者打掛
  • 生產者和消費者效率不平衡的情況,會導致消費者端效能下降,服務端卡頓或者崩潰

RabbitMQ 的組成

  • 生產者 producer
  • 消費者 consumer
  • 交換機 exchange

用於接受、分配訊息

  • 訊息 message
  • 佇列 queue

用於儲存生產者的訊息

  • 通道 channel AMQP

訊息推送使用的通道

  • 連線 connections

生成者或者消費者與Rabbit 建立的TCP 連線

  • 路由鍵 routingKey

用於把生成者的資料分配到交換器上

  • 繫結鍵 BindingKey

用於把交換器的訊息繫結到佇列上

  • 連線管理器 ConnectionFactory

應用程式與 Rabbit 之間建立連線的管理器,程式程式碼中使用

  • VHost

vhost 可以理解為虛擬 broker,即虛擬機器

其內部均含有獨立的 queue、exchange 和 binding 等

擁有獨立的許可權系統,做到資源隔離,資源高效利用

RabbitMQ 的六種模式

  • single

簡單的生產者生產訊息,放入佇列,消費者消費訊息

  • work

當生產者生產訊息的速度大於消費者消費的速度,就要考慮用 work 工作模式,這樣能提高處理速度提高負載

work 模式與 single 模式類似, 只是work 模式比 single 模式多了一些消費者

  • publish

應用場景:簡單訊息佇列的使用,一個生產者一個消費者

  • routing

訊息生產者將訊息傳送給交換機按照路由判斷,路由是字串(info) 當前產生的訊息攜帶路由字元(物件的方法),交換機根據路由的key

只能匹配上路由key對應的訊息佇列,對應的消費者才能消費訊息

  • topic

話題模式,一個訊息被多個消費者獲取,訊息的目標 queue 可用 BindingKey 以萬用字元

  • rpc

通過遠端過程呼叫的方式實現

儲存機制

  • 持久化訊息

持久化的訊息在到達佇列時就被寫入磁碟,持久化的訊息也會在記憶體中儲存一份備份,這樣可以提高一定的效能,當記憶體吃緊的時候會從記憶體中清除

  • 非持久化訊息

一般只儲存在記憶體中,在記憶體吃緊的時候會被換入到磁碟中,以節省記憶體空間

RabbitMQ中訊息可能有的幾種狀態

  • alpha

訊息內容(包括訊息體、屬性和 headers) 和訊息索引都儲存在記憶體中

  • beta

    訊息內容儲存在磁碟中,訊息索引儲存在記憶體中

  • gamma

訊息內容儲存在磁碟中,訊息索引在磁碟和記憶體中都有

  • delta

訊息內容和索引都在磁碟中

RabbitMQ 的佇列結構?

  • rabbit_amqqueue_process

負責協議相關的訊息處理,即接收生產者釋出的訊息、向消費者交付訊息、處理訊息的確認等

  • backing_queue

是訊息儲存的具體形式和引擎,並向 rabbit_amqqueue_process 提供相關的介面以供呼叫

交換器無法根據自身型別和路由鍵找到符合條件佇列時,會如何處理?

我們對交換機設定引數的時候,有一個標誌叫做 mandatory

  • 當mandatory標誌位設定為true時

如果exchange根據自身型別和訊息routingKey無法找到一個合適的queue儲存訊息,那麼broker就會呼叫basic.return方法將訊息返還給生產者

  • 當mandatory設定為false時

前置條件和上述保持一致,此時 broker會直接將訊息丟棄

如何保證訊息可靠性嘞?

  • 訊息從生產者到 MQ

由事務機制,確認機制 來保障

  • MQ 自身可靠性

由持久化、叢集、普通模式、映象模式來保證

  • MQ 訊息到消費者

由basicAck機制、死信佇列、訊息補償等機制來保證

叢集中的節點型別有哪些?

  • 記憶體節點

ram,將變更寫入記憶體。

  • 磁碟節點

disc,磁碟寫入操作

RabbitMQ中 要求最少有一個磁碟節點

如何保證 RabbitMQ 訊息佇列的高可用?

RabbitMQ中有三種模式來保證:

  • 單機模式

一般是本地啟動,自己學習和測試使用,不會用在生產環境上

  • 普通叢集模式

在多臺機器上啟動多個 RabbitMQ 例項,每個機器啟動一個

  • 映象叢集模式

RabbitMQ的高可用模式

跟普通叢集模式不一樣的是,建立的 queue,無論後設資料(後設資料指 RabbitMQ 的配置資料)還是 queue 裡的訊息都會存在於多個例項上,

然後每次寫訊息到 queue 的時候,都會自動把訊息到多個例項的 queue 裡進行訊息同步

參考資料:

RabbitMQ Tutorials

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

本作品採用《CC 協議》,轉載必須註明作者和本文連結
關注微信公眾號:小魔童哪吒

相關文章