持續輸出面試題之RabbitMQ篇

開篇介紹

你們好,我是Java最全面試題庫的提褲姐,今天這篇是中間件面試題系列的第一篇,主要總結了RabbitMQ相關的面試題;在後續,會沿着第一篇開篇的知識線路一直總結下去,作到日更!若是我能作到百日百更,但願你也能夠跟着百日百刷,一百天養成一個好習慣。面試

什麼是RabbitMQ?爲何使用RabbitMQ?有什麼好處?

RabbitMQ是一款開源的,Erlang編寫的,基於AMQP協議的,消息中間件;
能夠用它來:解耦異步削峯服務器

  • 優勢:解耦、異步、削峯;
  • 缺點:下降了系統的穩定性:系統中使用了消息隊列,若是消息隊列掛了,那麼系統也會掛掉。所以,系統可用性會下降;

加入了消息隊列,要多考慮不少方面的問題,好比:一致性問題、如何保證消息不被重複消費、如何保證消息可靠性傳輸等。所以,須要考慮的東西更多,複雜性增大。網絡

RabbitMQ基本概念有哪些?

  • Broker: 消息隊列服務器實體
  • Exchange: 消息交換機,它指定消息按特定規則,路由到哪一個隊列
  • Queue: 消息隊列載體,每一個消息都會被投入到一個或多個隊列
  • Binding: 綁定,它的做用就是把exchange和queue按照路由規則綁定起來
  • Routing Key: 路由關鍵字,exchange根據這個關鍵字進行消息投遞
  • VHost: vhost 能夠理解爲虛擬 broker ,即 mini-RabbitMQ server。其內部均含有獨立的 queue、exchange 和 binding 等,擁有獨立的權限系統,能夠作到 vhost 範圍的用戶控制。
  • Producer: 消息生產者
  • Consumer: 消息消費者
  • Channel: 消息通道,在客戶端的每一個鏈接裏,可創建多個channel,每一個channel表明一個會話任務

如何保證RabbitMQ不被重複消費?

正常狀況下,消費者在消費消息的時候,消費完畢後,會發送一個確認消息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息隊列中刪除;異步

可是由於網絡傳輸等等故障,確認信息沒有傳送到消息隊列,致使消息隊列不知道本身已經消費過該消息了,再次將消息分發給其餘的消費者。操作系統

解決思路:
保證消息的惟一性,就算是屢次傳輸,不要讓消息的屢次消費帶來影響;保證消息等冪性;
好比:在寫入消息隊列的數據作惟一標識,消費消息時,根據惟一標識判斷是否消費過;線程

RabbitMQ 概念裏的 channel、exchange 和 queue 是邏輯概念,仍是對應着進程實體?分別起什麼做用?

queue 具備本身的 erlang 進程;
exchange 內部實現爲保存 binding 關係的查找表;
channel 是實際進行路由工做的實體,即負責按照 routing_key 將 message 投遞給 queue 。code

由 AMQP 協議描述可知,channel 是真實 TCP 鏈接之上的虛擬鏈接,全部 AMQP 命令都是經過 channel 發送的,且每個 channel 有惟一的 ID。一個 channel 只能被單獨一個操做系統線程使用,故投遞到特定 channel 上的 message 是有順序的。但一個操做系統線程上容許使用多個 channel 。server

rabbitmq 消息是如何路由的?

從概念上來講,消息路由必須有三部分:交換器、路由、綁定。中間件

生產者把消息發佈到交換器上;綁定決定了消息如何從路由器路由到特定的隊列;消息最終到達隊列,並被消費者接收。
消息發佈到交換器時,消息將擁有一個路由鍵(routing key),在消息建立時設定。
經過隊列路由鍵,能夠把隊列綁定到交換器上。
消息到達交換器後,RabbitMQ會將消息的路由鍵與隊列的路由鍵進行匹配(針對不一樣的交換器有不一樣的路由規則)。若是可以匹配到隊列,則消息會投遞到相應隊列中;若是不能匹配到任何隊列,消息將進入 「黑洞」。rabbitmq

經常使用的交換器主要分爲一下三種:

  • direct:若是路由鍵徹底匹配,消息就被投遞到相應的隊列
  • fanout:若是交換器收到消息,將會廣播到全部綁定的隊列上
  • topic:可使來自不一樣源頭的消息可以到達同一個隊列。 使用topic交換器時,可使用通配符,好比:「*」 匹配特定位置的任意文本, 「.」 把路由鍵分爲了幾部分,「#」 匹配全部規則等。
特別注意:發往topic交換器的消息不能隨意的設置選擇鍵(routing_key),必須是由"."隔開的一系列的標識符組成。

如何保證RabbitMQ消息的可靠傳輸?

消息不可靠的狀況多是消息丟失,劫持等緣由
丟失又分爲:

  • 生產者丟失消息
  • 消息列表丟失消息
  • 消費者丟失消息

生產者丟失消息:
從生產者弄丟數據這個角度來看,RabbitMQ提供transaction機制confirm模式來確保生產者不丟消息;

  • transaction機制:發送消息前,開啓事務(channel.txSelect()),而後發送消息,若是發送過程當中出現什麼異常,事務就會回滾(channel.txRollback()),若是發送成功則提交事務(channel.txCommit())。
  • confirm模式(用的居多):一旦channel進入confirm模式,全部在該信道上發佈的消息都將會被指派一個惟一的ID(從1開始),一旦消息被投遞到全部匹配的隊列以後; RabbitMQ就會發送一個ACK給生產者(包含消息的惟一ID),這就使得生產者知道消息已經正確到達目的隊列了;

若是RabbitMQ沒能處理該消息,則會發送一個Nack消息給你,你能夠進行重試操做。

消息隊列丟數據:
消息持久化,處理消息隊列丟數據的狀況,通常是開啓持久化磁盤的配置:
將隊列的持久化標識durable設置爲true,則表明是一個持久的隊列 發送消息的時候將 deliveryMode=2 這樣設置之後,即便RabbitMQ掛了,重啓後也能恢復數據

消費者丟失消息:
消費者丟數據通常是由於採用了自動確認消息模式,改成手動確認消息
消費者在收到消息以後,處理消息以前,會自動回覆RabbitMQ已收到消息; 若是這時處理消息失敗,就會丟失該消息;
解決方案:處理消息成功後,手動回覆確認消息。

如何保證RabbitMQ消息的順序性?

一、單線程消費保證消息的順序性;
二、對消息進行編號,消費者處理消息是根據編號處理消息;

死信隊列和延遲隊如何使用?

死信隊列:
死信,顧名思義就是沒法被消費的消息,字面意思能夠這樣理解,通常來講,producer將消息投遞到broker或者直接到queue裏了,consumer從queue取出消息進行消費,但某些時候因爲特定的緣由致使queue中的某些消息沒法被消費,這樣的消息若是沒有後續的處理,就變成了死信,有死信,天然就有了死信隊列;

死信消息:
一、消息被拒絕(Basic.RejectBasic.Nack)而且設置 requeue 參數的值爲 false
二、消息過時了
三、隊列達到最大的長度

過時消息:
在 rabbitmq 中存在2種方可設置消息的過時時間,

  • 第一種經過對隊列進行設置,這種設置後,該隊列中全部的消息都存在相同的過時時間,
  • 第二種經過對消息自己進行設置,那麼每條消息的過時時間都不同。

若是同時使用這2種方法,那麼以過時時間小的那個數值爲準。當消息達到過時時間尚未被消費,那麼那個消息就成爲了一個 死信 消息。

隊列設置:在隊列申明的時候使用 x-message-ttl 參數,單位爲 毫秒
單個消息設置:是設置消息屬性的 expiration 參數的值,單位爲 毫秒

延時隊列:在rabbitmq中不存在延時隊列,可是咱們能夠經過設置消息的過時時間和死信隊列來模擬出延時隊列。消費者監聽死信交換器綁定的隊列,而不要監聽消息發送的隊列。

相關文章
相關標籤/搜索