1 、 exchange queue binding-key routing-key概念及相互間的關係
1.queue :存儲消息的隊列,能夠指定name來惟一肯定
2.exchange:交換機(經常使用有三種),用於接收生產者發來的消息,並經過binding-key 與 routing-key 的匹配關係來決定將消息分發到指定queue
Direct(路由模式):徹底匹配 > 當消息的routing-key 與 exchange和queue間的binding-key徹底匹配時,將消息分發到該queue
Fanout (訂閱模式):與binding-key和routing-key無關,將接受到的消息分發給有綁定關係的全部隊列(不論binding-key和routing-key是什麼)
Topic (通配符模式):用消息的routing-key 與 exchange和queue間的binding-key 進行模式匹配,當知足規則時,分發到知足規則的全部隊列
2.爲何要使用rabbitmq數據庫
採用AMQP高級消息隊列協議的一種消息隊列技術,
實現了服務之間的高度解耦
1.在分佈式系統下具有異步,削峯,負載均衡等一系列高級功能;
2.擁有持久化的機制,進程消息,隊列中的信息也能夠保存下來。
3.實現消費者和生產者之間的解耦。
4.對於高併發場景下,削峯限流,利於數據庫的操做。
5.可使用消息隊列達到異步下單的效果,排隊中,後臺進行邏輯下單。
3.使用rabbitmq的場景安全
1.服務間異步通訊
2.順序消費
3.定時任務
4.請求削峯
4.如何確保消息正確地發送至RabbitMQ? 如何確保消息接收方消費了消息?如何避免消息重複投遞或重複消費?服務器
持久化有兩種方式 MQ事物(太耗性能,不使用)與confirm模式。
發送方確認模式:
將信道設置成confirm模式(發送方確認模式),則全部在信道上發佈的消息都會被指派一個惟一的ID。
一旦消息被投遞到目的隊列後,或者消息被寫入磁盤後(可持久化的消息),信道會發送一個確認給生產者(包含消息惟一ID)。
若是RabbitMQ發生內部錯誤從而致使消息丟失,會發送一條nack(not acknowledged,未確認)消息。
發送方確認模式是異步的,生產者應用程序在等待確認的同時,能夠繼續發送消息。當確認消息到達生產者應用程序,生產者應用程序的回調方法就會被觸發來處理確認消息。
接收方確認機制
接收方消息確認機制:消費者接收每一條消息後都必須進行確認(消息接收和消息確認是兩個不一樣操做)。只有消費者確認了消息,RabbitMQ才能安全地把消息從隊列中刪除。
這裏並無用到超時機制,RabbitMQ僅經過Consumer的鏈接中斷來確認是否須要從新發送消息。也就是說,只要鏈接不中斷,RabbitMQ給了Consumer足夠長的時間來處理消息。保證數據的最終一致性;
下面羅列幾種特殊狀況:
若是消費者接收到消息,在確認以前斷開了鏈接或取消訂閱,RabbitMQ會認爲消息沒有被分發,而後從新分發給下一個訂閱的消費者。(可能存在消息重複消費的隱患,須要去重)
若是消費者接收到消息卻沒有確認消息,鏈接也未斷開,則RabbitMQ認爲該消費者繁忙,將不會給該消費者分發更多的消息。
在消息生產時,MQ內部針對每條生產者發送的消息生成一個inner-msg-id,做爲去重的依據(消息投遞失敗並重傳),避免重複的消息進入隊列;
在消息消費時,要求消息體中必需要有一個bizId(對於同一業務全局惟一,如支付ID、訂單ID、帖子ID等)做爲去重的依據,避免同一條消息被重複消費。
消息持久化,固然前提是隊列、交換機必須持久化
RabbitMQ確保持久性消息能從服務器重啓中恢復的方式是,將它們寫入磁盤上的一個持久化日誌文件,當發佈一條持久性消息到持久交換器上時,Rabbit會在消息提交到日誌文件後才發送響應。
一旦消費者從持久隊列中消費了一條持久化消息,RabbitMQ會在持久化日誌中把這條消息標記爲等待垃圾收集。若是持久化消息在被消費以前RabbitMQ重啓,那麼Rabbit會自動重建交換器和隊列(以及綁定),並從新發布持久化日誌文件中的消息到合適的隊列。
消息持久化
ACK確認機制
設置集羣鏡像模式
消息補償機制
5.消息基於什麼傳輸?網絡
因爲TCP鏈接的建立和銷燬開銷較大,且併發數受系統資源限制,會形成性能瓶頸。RabbitMQ使用信道的方式來傳輸數據。信道是創建在真實的TCP鏈接內的虛擬鏈接,且每條TCP鏈接上的信道數量沒有限制。
6.消息如何分發?
若該隊列至少有一個消費者訂閱,消息將以循環(round-robin)的方式發送給消費者。每條消息只會分發給一個訂閱的消費者(前提是消費者可以正常處理消息並進行確認)。
經過路由可實現多消費的功能
7.消息怎麼路由?架構
消息提供方->路由->一至多個隊列
消息發佈到交換器時,消息將擁有一個路由鍵(routing key),在消息建立時設定。
經過隊列路由鍵,能夠把隊列綁定到交換器上。
消息到達交換器後,RabbitMQ會將消息的路由鍵與隊列的路由鍵進行匹配(針對不一樣的交換器有不一樣的路由規則);
經常使用的交換器主要分爲一下三種:
fanout:若是交換器收到消息,將會廣播到全部綁定的隊列上
direct:若是路由鍵徹底匹配,消息就被投遞到相應的隊列
topic:可使來自不一樣源頭的消息可以到達同一個隊列。 使用topic交換器時,可使用通配符
8.使用RabbitMQ有什麼好處?併發
服務間高度解耦,
異步通訊性能高,
流量削峯
缺點:增長了系統複雜度,系統可用性低,外部依賴過多,一致性問題。
持久化的缺地就是下降了服務器的吞吐量,由於使用的是磁盤而非內存存儲,從而下降了吞吐量。可儘可能使用 ssd 硬盤來緩解吞吐量的問題。
9.rabbitmq的集羣負載均衡
主備模式:
普通集羣模式:節點數據不復制,消息在某一臺中,節點間通訊,一臺掛了 就不可用了。
鏡像集羣模式:
你建立的queue,不管元數據仍是queue裏的消息都會存在於多個實例上,而後每次你寫消息到queue的時候,都會自動把消息到多個實例的queue裏進行消息同步。
好處在於,你任何一個機器宕機了,沒事兒,別的機器均可以用。壞處在於,第一,這個性能開銷也太大了吧,消息同步全部機器,致使網絡帶寬壓力和消耗很重!第二,這麼玩兒,就沒有擴展性可言了,若是某個queue負載很重,你加機器,新增的機器也包含了這個queue的全部數據,並無辦法線性擴展你的queue
十、Kafka的高可用
Kafka 一個最基本的架構認識:由多個 broker 組成,每一個 broker 是一個節點;你建立一個 topic,這個 topic 能夠劃分爲多個 partition,每一個 partition 能夠存在於不一樣的 broker 上,每一個 partition 就放一部分數據。異步
這就是自然的分佈式消息隊列,就是說一個 topic 的數據,是分散放在多個機器上的,每一個機器就放一部分數據。分佈式
寫數據的時候,生產者就寫 leader,而後 leader 將數據落地寫本地磁盤,接着其餘 follower 本身主動從 leader 來 pull 數據。一旦全部 follower 同步好數據了,就會發送 ack 給 leader,leader 收到全部 follower 的 ack 以後,就會返回寫成功的消息給生產者。(固然,這只是其中一種模式,還能夠適當調整這個行爲)高併發
消費的時候,只會從 leader 去讀,可是隻有當一個消息已經被全部 follower 都同步成功返回 ack 的時候,這個消息纔會被消費者讀到。
十一、什麼狀況下會出現 blackholed 問題?
答:blackholed 問題是指,向 exchange 投遞了 message ,而因爲各類緣由致使該 message 丟失,但發送者殊不知道。可致使 blackholed 的狀況:1.向未綁定 queue 的 exchange 發送 message;2.exchange 以 binding_key key_A綁定了 queue queue_A,但向該 exchange 發送 message 使用的 routing_key 倒是 key_B。
十二、如何防止出現 blackholed 問題?
答:沒有特別好的辦法,只能在具體實踐中經過各類方式保證相關 fabric 的存在。另外,若是在執行 Basic.Publish 時設置 mandatory=true ,則在遇到可能出現 blackholed 狀況時,服務器會經過返回 Basic.Return 告之當前 message 沒法被正確投遞(內含緣由 312 NO_ROUTE)。
1三、Consumer Cancellation Notification 機制用於什麼場景?
答:用於保證當鏡像 queue 中 master 掛掉時,鏈接到 slave 上的 consumer 能夠收到自身 consume 被取消的通知,進而能夠從新執行 consume 動做重新選出的 master 出得到消息。若不採用該機制,鏈接到 slave 上的 consumer 將不會感知 master 掛掉這個事情,致使後續沒法再收到新 master 廣播出來的 message 。另外,由於在鏡像 queue 模式下,存在將 message 進行 requeue 的可能,因此實現 consumer 的邏輯時須要可以正確處理出現重複 message 的狀況。
1四、Basic.Reject 的用法是什麼?
答:該信令可用於 consumer 對收到的 message 進行 reject 。若在該信令中設置 requeue=true,則當 RabbitMQ server 收到該拒絕信令後,會將該 message 從新發送到下一個處於 consume 狀態的 consumer 處(理論上仍可能將該消息發送給當前 consumer)。若設置 requeue=false ,則 RabbitMQ server 在收到拒絕信令後,將直接將該 message 從 queue 中移除。
另一種移除 queue 中 message 的小技巧是,consumer 回覆 Basic.Ack 但不對獲取到的 message 作任何處理。
而 Basic.Nack 是對 Basic.Reject 的擴展,以支持一次拒絕多條 message 的能力。
1五、什麼是死信呢?什麼樣的消息會變成死信呢?
方便咱們查看消息失敗的緣由了
消息被拒絕(basic.reject或basic.nack)而且requeue=false.
消息TTL過時
隊列達到最大長度(隊列滿了,沒法再添加數據到mq中)
1六、若是讓你寫一個消息隊列,該如何進行架構設計?說一下你的思路。
快速擴容, 分佈式, 數據持久化, 磁盤順序讀寫, 高可用, 消息0丟失(ack)
1七、rabbitMQ怎麼作的持久化
寫入文件前會有一個Buffer,大小爲1M(1048576),數據在寫入文件時,首先會寫入到這個Buffer,若是Buffer已滿,則會將Buffer寫入到文件(未必刷到磁盤)
有個固定的刷盤時間:25ms,也就是無論Buffer滿不滿,每隔25ms,Buffer裏的數據及未刷新到磁盤的文件內容一定會刷到磁盤
每次消息寫入後,若是沒有後續寫入請求,則會直接將已寫入的消息刷到磁盤:使用Erlang的receive x after 0來實現,只要進程的信箱裏沒有消息,則產生一個timeout消息,而timeout會觸發刷盤操做
1八、RabbitMQ、kafka之間的比較
一、 RabbitMq比kafka成熟,在可用性上,穩定性上,可靠性上,RabbitMq超過kafka。rabbitMq 延遲度低。
二、 Kafka設計的初衷就是處理日誌的,能夠看作是一個日誌系統,針對性很強,因此它並無具有一個成熟MQ應該具有的特性(不支持事物)
三、 Kafka的性能(吞吐量、tps)比RabbitMq要強,這篇文章的做者認爲,二者在這方面沒有可比性。
4.技術上面,使用rabbitMq比kafka 長,二者社區活躍度都高。
5.RocketMQ 阿里出品,社區活躍度不是很高,技術實力強大的公司可選擇。