「SpringBoot MQ 系列」RabbitMq 核心知識點小結

「SpringBoot 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的內部結構圖

「SpringBoot MQ 系列」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策略

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

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

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

舉例說明

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

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

注意

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

b. Topic策略

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

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

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

一個更直觀的實例如下

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

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

c. Fanout策略

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

廣播策略,忽略routing key 和 binding 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 集群互聯。
「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

3. 鏡像模式

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

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

4. 多活模式

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

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

「SpringBoot MQ 系列」RabbitMq 核心知識點小結

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

IV. 其他

0. 項目

  • 工程:https://github.com/liuyueyi/spring-boot-demo

1. 相關博文

  • RabbitMQ Tutorials
  • MQ和RabbitMQ作用特點
  • RabbitMq基礎教程之基本概念
  • RabbitMQ學習(六)——消息確認機制(Confirm模式)
  • RabbitMQ 的4種集群架構
  • Rabbitmq是如何來保證事務的
  • rabbitmq消息一致性問題

2. 一灰灰Blog

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

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

  • 一灰灰Blog個人博客 https://blog.hhui.top
  • 一灰灰Blog-Spring專題博客 http://spring.hhui.top


分享到:


相關文章: