![「SpringBoot MQ 系列」RabbitMq 核心知識點小結](http://p2.ttnews.xyz/loading.gif)
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 核心知識點小結](http://p2.ttnews.xyz/loading.gif)
從上圖也可以發現幾個基本概念(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 key與binding key完全匹配
- 如果一個隊列綁定到交換機要求路由鍵為dog
- 只轉發routing key 標記為dog的消息,
- 不會轉發dog.puppy,也不會轉發“dog.guard”等等
- 它是完全匹配、單播的模式
舉例說明
Exchange和兩個隊列綁定在一起:
- Q1的bindingkey是orange
- Q2的binding key是black和green.
- 當Producer 發佈一個消息,其routing key是orange時, exchange會把它放到Q1上, 如果是black或green就會到Q2上, 其餘的Message被丟棄
注意
- 當有多個隊列綁定到同一個Exchange,且binding key相同時,這時消息會分發給所有滿足條件的隊列
b. Topic策略
這個策略可以看成是Direct策略的升級版,通過routing key與 bingding key的模式匹配方式來分發消息
簡單來講,直接策略是完全精確匹配,而topic則支持正則匹配,滿足某類指定規則的(如以xxx開頭的路由鍵),可以將消息分發過去
- # 匹配0個或多個單詞
- * 匹配不多不少一個單詞
一個更直觀的實例如下
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策略
廣播策略,忽略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 集群互聯。
如上圖,有兩個異地的 MQ 集群(可以是更多的集群),當用戶在地區 1 這裡下單了,系統發消息到 1 區的 MQ 服務器,發現 MQ 服務已超過設定的閾值,負載過高,這條消息就會被轉到 地區 2 的 MQ 服務器上,由 2 區的去執行後面的業務邏輯,相當於分攤我們的服務壓力。
3. 鏡像模式
非常經典的 mirror 鏡像模式,保證 100% 數據不丟失。在實際工作中也是用得最多的,並且實現非常的簡單,一般互聯網大廠都會構建這種鏡像集群模式。
如上圖,用 KeepAlived 做了 HA-Proxy 的高可用,然後有 3 個節點的 MQ 服務,消息發送到主節點上,主節點通過 mirror 隊列把數據同步到其他的 MQ 節點,這樣來實現其高可靠
4. 多活模式
也是實現異地數據複製的主流模式,因為 shovel 模式配置比較複雜,所以一般來說,實現異地集群的都是採用這種雙活 或者 多活模型來實現的。這種模式需要依賴 rabbitMQ 的 federation 插件,可以實現持續的,可靠的 AMQP 數據通信,多活模式在實際配置與應用非常的簡單
rabbitMQ 部署架構採用雙中心模式(多中心),那麼在兩套(或多套)數據中心各部署一套 rabbitMQ 集群,各中心的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
閱讀更多 小灰灰blog 的文章