【SpringBoot MQ 系列】RabbitMq 核心知識點小結

【MQ 系列】RabbitMq 核心知識點小結

以下內容,部分取材於官方教程,部分來源網絡博主的分享,如有興趣瞭解更多詳細的知識點,可以在本文最後的文章列表中獲取原地址

RabbitMQ 是一個基於 AMQP 協議實現的企業級消息系統,想要順暢的玩耍的前提是得先了解它,本文將主要介紹 rabbitmq 的一些基本知識點

  • 特點
  • 基本概念
  • 消息投遞消費的幾種姿勢
  • 事務
  • 集羣

I. 基本知識點

它是採用 Erlang 語言實現的 AMQP(Advanced Message Queued Protocol)的消息中間件,最初起源於金融系統,用在分佈式系統存儲轉發消息,目前廣泛應用於各類系統用於解耦、削峯

1.特點

首先得了解一下 rabbitmq 的特點,看看是否滿足我們的系統需求(畢竟學習一個框架也是要不少時間的)

以下內容來自: MQ 和 RabbitMQ 作用特點

主要特點,大致可以歸納爲以下幾個

  • 可靠性:通過支持消息持久化,支持事務,支持消費和傳輸的 ack 等來確保可靠性
  • 路由機制:支持主流的訂閱消費模式,如廣播,訂閱,headers 匹配等
  • 擴展性:多個 RabbitMQ 節點可以組成一個集羣,也可以根據實際業務情況動態地擴展集羣中節點。
  • 高可用性:隊列可以在集羣中的機器上設置鏡像,使得在部分節點出現問題的情況下隊仍然可用。
  • 多種協議:RabbitMQ 除了原生支持 AMQP 協議,還支持 STOMP,MQTT 等多種消息中間件協議。
  • 多語言客戶端:RabbitMQ 幾乎支持所有常用語言,比如 Jav a、Python、Ruby、PHP、C#、JavaScript 等。
  • 管理界面:RabbitMQ 提供了一個易用的用戶界面,使得用戶可以監控和管理消息、集羣中的節點等。
  • 插件機制:RabbitMQ 提供了許多插件,以實現從多方面進行擴展,當然也可以編寫自己的插件。

2. 基本概念

下圖爲 rabbitmq 的內部結構圖

從上圖也可以發現幾個基本概念(Message, Publisher, Exchange, Binding, Queue, Channel, Consuer, Virtual host)

下面逐一進行說明

a. Message

具體的消息,包含消息頭(即附屬的配置信息)和消息體(即消息的實體內容)

由發佈者,將消息推送到 Exchange,由消費者從 Queue 中獲取

b. Publisher

消息生產者,負責將消息發佈到交換器(Exchange)

c. Exchange

交換器,用來接收生產者發送的消息並將這些消息路由給服務器中的隊列

d. Binding

綁定,用於給 Exchange 和 Queue 建立關係,從而決定將這個交換器中的哪些消息,發送到對應的 Queue

e. Queue

消息隊列,用來保存消息直到發送給消費者

它是消息的容器,也是消息的終點

一個消息可投入一個或多個隊列

消息一直在隊列裏面,等待消費者連接到這個隊列將其取走

f. Connection

連接,內部持有一些 channel,用於和 queue 打交道

g. Channel

信道(通道),MQ 與外部打交道都是通過 Channel 來的,發佈消息、訂閱隊列還是接收消息,這些動作都是通過 Channel 完成;

簡單來說就是消息通過 Channel 塞進隊列或者流出隊列

h. Consumer

消費者,從消息隊列中獲取消息的主體

i. Virtual Host

虛擬主機,表示一批交換器、消息隊列和相關對象。

虛擬主機是共享相同的身份認證和加密環境的獨立服務器域。

每個 vhost 本質上就是一個 mini 版的 RabbitMQ 服務器,擁有自己的隊列、交換器、綁定和權限機制。

vhost 是 AMQP 概念的基礎,必須在連接時指定,RabbitMQ 默認的 vhost 是 /

可以理解爲 db 中的數據庫的概念,用於邏輯拆分

j. Broker

消息隊列服務器實體

3. 消息投遞消費

從前面的內部結構圖可以知曉,消息由生產者發佈到 Exchange,然後通過路由規則,分發到綁定 queue 上,供消費者獲取消息

接下來我們看一下 Exchange 支持的四種策略

a. Direct 策略

消息中的路由鍵(routing key)如果和 Binding 中的 binding key 一致, 交換器就將消息發到對應的隊列中

簡單來講,就是rounting keybinding key完全匹配

  • 如果一個隊列綁定到交換機要求路由鍵爲dog
  • 只轉發routing key 標記爲dog的消息,
  • 不會轉發dog.puppy,也不會轉發“dog.guard”等等
  • 它是完全匹配、單播的模式

舉例說明

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1dB9B8W4-1581575072741)(https://spring.hhui.top/spring-blog/imgs/200212/02.jpg)]

Exchange 和兩個隊列綁定在一起:

  • Q1 的 bindingkey 是 orange
  • Q2 的 binding key 是 black 和 green.
  • 當 Producer 發佈一個消息,其routing keyorange時, exchange 會把它放到 Q1 上, 如果是blackgreen就會到 Q2 上, 其餘的 Message 被丟棄

注意

  • 當有多個隊列綁定到同一個 Exchange,且 binding key 相同時,這時消息會分發給所有滿足條件的隊列

b. Topic 策略

這個策略可以看成是 Direct 策略的升級版,通過routing keybingding key的模式匹配方式來分發消息

簡單來講,直接策略是完全精確匹配,而 topic 則支持正則匹配,滿足某類指定規則的(如以 xxx 開頭的路由鍵),可以將消息分發過去

  • # 匹配 0 個或多個單詞
  • * 匹配不多不少一個單詞

一個更直觀的實例如下

Producer 發送消息時需要設置 routing_key,

  • Q1 的 binding key 是*.orange.*
  • Q2 是 *.*.rabbitlazy.#
  • 發佈一個routing keytest.orange.mm 消息,則會路由到 Q1;
    • 注意: 如果是routng keytest.orange則無法路由到 Q1,
    • 因爲 Q1 的規則是三個單詞,中間一個爲 orange,不滿足這個規則的都無效
  • 發佈一個routing keytest.qq.rabbit或者lazy.qq的消息 都可以分發到 Q2;即路由 key 爲三個單詞,最後一個爲 rabbit 或者不限制單詞個數,主要第一個是 lazy 的消息,都可以分發過來
  • 如果發佈的是一個test.orange.rabbit消息,則 Q1 和 Q2 都可以滿足
    • 注意: 這時兩個隊列都會接受到這個消息

c. Fanout 策略

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lIJlWUcl-1581575072744)(https://spring.hhui.top/spring-blog/imgs/200212/05.jpg)]

廣播策略,忽略routing keybinding key,將消息分發給所有綁定在這個 exchange 上的 queue

d. Headers 策略

這個實際上用得不多,它是根據 Message 的一些頭部信息來分發過濾 Message,忽略 routing key 的屬性,如果 Header 信息和 message 消息的頭信息相匹配

II. 消息一致性問題

在進入 rabbitmq 如何保證一致性之前,我們先得理解,什麼是消息一致性?

1. 一致性問題

數據的一致性是什麼

按照我個人的粗淺理解,我認爲的消息一致性,應該包含下面幾個

  • 生產者,確保消息發佈成功
    • 消息不會丟
    • 順序不會亂
    • 消息不會重複(如重傳,導致發佈一次,卻出現多個消息)
  • 消費者,確保消息消費成功
    • 有序消費
    • 不重複消費

發送端

爲了確保發佈者推送的消息不會丟失,我們需要消息持久化

  • broker 持久化消息

爲了確定消息正確接收

  • publisher 需要知道消息投遞併成功持久化

2. 持久化

這裏的持久化,主要是指將內存中的消息保存到磁盤,避免 mq 宕機導致的內存中消息丟失;然而單純的持久化,只是保證一致性的其中一個要素,比如 publisher 將消息發送到 exchange,在 broker 持久化的工程中,宕機了導致持久化失敗,而 publisher 並不知道持久化失敗,這個時候就會出現數據丟失,爲了解決這個問題,rabbitmq 提供了事務機制

3. 事務機制

事務機制能夠解決生產者與 broker 之間消息確認的問題,只有消息成功被 broker 接受,事務才能提交成功,否則就進行事務回滾操作並進行消息重發。但是使用事務機制會降低 RabbitMQ 的消息吞吐量,不適用於需要發佈大量消息的業務場景。

注意,事務是同步的

4. 消息確認機制

RabbitMQ 學習(六)——消息確認機制(Confirm 模式)

消息確認機制,可以區分爲生產端和消費端

生產端

  • 生產者將信道設置成 Confirm 模式,一旦信道進入 Confirm 模式,所有在該信道上面發佈的消息都會被指派一個唯一的 ID(以 confirm.select 爲基礎從 1 開始計數),
  • 一旦消息被投遞到所有匹配的隊列之後,Broker 就會發送一個確認給生產者(包含消息的唯一 ID),這就使得生產者知道消息已經正確到達目的隊列了,
  • 如果消息和隊列是可持久化的,那麼確認消息會將消息寫入磁盤之後發出,
  • Broker 回傳給生產者的確認消息中 deliver-tag 域包含了確認消息的序列號(此外 Broker 也可以設置 basic.ack 的 multiple 域,表示到這個序列號之前的所有消息都已經得到了處理)

Confirm 模式屬性異步,publisher 發佈一條消息之後,在等信道返回確認的同時,依然可以繼續發送下一條消息,所以小概率會出現投遞的消息順序和 broker 中持久化消息順序不一致的問題

一般從編程角度出發,Confirm 模式有三種姿勢

  • 普通 Confirm 模式:發送一條消息之後,等到服務器 confirm,然後再發佈下一條消息(串行發佈)
  • 批量 Confirm 模式:發送一批消息之後,等到服務器 confirm,然後再發佈下一批消息(如果失敗,這一批消息全部重複,所以會有重複問題)
  • 異步 Confirm 模式:提供一個回調方法,服務器 confirm 之後,觸發回調方法,因此不會阻塞下一條消息的發送

消費端

ACK 機制是消費者從 RabbitMQ 收到消息並處理完成後,反饋給 RabbitMQ,RabbitMQ 收到反饋後纔將此消息從隊列中刪除。

  • 如果一個消費者在處理消息出現了網絡不穩定、服務器異常等現象,那麼就不會有 ACK 反饋,RabbitMQ 會認爲這個消息沒有正常消費,會將消息重新放入隊列中
  • 如果在集羣的情況下,RabbitMQ 會立即將這個消息推送給這個在線的其他消費者。這種機制保證了在消費者服務端故障的時候,不丟失任何消息和任務
  • 消息永遠不會從 RabbitMQ 中刪除,只有當消費者正確發送 ACK 反饋,RabbitMQ 確認收到後,消息纔會從 RabbitMQ 服務器的數據中刪除

III. 集羣

按照目前的發展趨勢,一個不支持集羣的中間件基本上是不會有市場的;rabbitmq 也是支持集羣的,下面簡單的介紹一下常見的 4 種集羣架構模式

以下內容來自網上博文,詳情請點擊右邊:RabbitMQ 的 4 種集羣架構

1. 主備模式

這個屬於常見的集羣模式了,但又不太一樣

主節點提供讀寫,備用節點不提供讀寫。如果主節點掛了,就切換到備用節點,原來的備用節點升級爲主節點提供讀寫服務,當原來的主節點恢復運行後,原來的主節點就變成備用節點

2. 遠程模式

遠程模式可以實現雙活的一種模式,簡稱 shovel 模式,所謂的 shovel 就是把消息進行不同數據中心的複製工作,可以跨地域的讓兩個 MQ 集羣互聯,遠距離通信和複製。

  • Shovel 就是我們可以把消息進行數據中心的複製工作,我們可以跨地域的讓兩個 MQ 集羣互聯。

如上圖,有兩個異地的 MQ 集羣(可以是更多的集羣),當用戶在地區 1 這裏下單了,系統發消息到 1 區的 MQ 服務器,發現 MQ 服務已超過設定的閾值,負載過高,這條消息就會被轉到 地區 2 的 MQ 服務器上,由 2 區的去執行後面的業務邏輯,相當於分攤我們的服務壓力。

3. 鏡像模式

非常經典的 mirror 鏡像模式,保證 100% 數據不丟失。在實際工作中也是用得最多的,並且實現非常的簡單,一般互聯網大廠都會構建這種鏡像集羣模式。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zi7HefEn-1581575072747)(https://spring.hhui.top/spring-blog/imgs/200212/07.jpg)]

如上圖,用 KeepAlived 做了 HA-Proxy 的高可用,然後有 3 個節點的 MQ 服務,消息發送到主節點上,主節點通過 mirror 隊列把數據同步到其他的 MQ 節點,這樣來實現其高可靠

4. 多活模式

也是實現異地數據複製的主流模式,因爲 shovel 模式配置比較複雜,所以一般來說,實現異地集羣的都是採用這種雙活 或者 多活模型來實現的。這種模式需要依賴 rabbitMQ 的 federation 插件,可以實現持續的,可靠的 AMQP 數據通信,多活模式在實際配置與應用非常的簡單

rabbitMQ 部署架構採用雙中心模式(多中心),那麼在兩套(或多套)數據中心各部署一套 rabbitMQ 集羣,各中心的 rabbitMQ 服務除了需要爲業務提供正常的消息服務外,中心之間還需要實現部分隊列消息共享。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZkItTtLw-1581575072749)(https://spring.hhui.top/spring-blog/imgs/200212/08.jpg)]

federation 插件是一個不需要構建 cluster ,而在 brokers 之間傳輸消息的高性能插件,federation 插件可以在 brokers 或者 cluster 之間傳輸消息,連接的雙方可以使用不同的 users 和 virtual hosts,雙方也可以使用不同版本的 rabbitMQ 和 erlang。federation 插件使用 AMQP 協議通信,可以接受不連續的傳輸。federation 不是建立在集羣上的,而是建立在單個節點上的,如圖上黃色的 rabbit node 3 可以與綠色的 node1、node2、node3 中的任意一個利用 federation 插件進行數據同步。

IV. 其他

0. 項目

1. 相關博文

2. 一灰灰 Blog

盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激

下面一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛

一灰灰blog

發佈了197 篇原創文章 · 獲贊 50 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章