非常強悍的 RabbitMQ 總結,寫得真好!

前言

RabbitMQ 是基於 AMQP 協議的,通過使用通用協議就可以做到在不同語言之間傳遞。

AMQP 協議

核心概念

  1. server:又稱 broker,接受客戶端連接,實現 AMQP 實體服務。

  2. connection:連接和具體 broker 網絡連接。

  3. channel:網絡信道,幾乎所有操作都在 channel 中進行,channel 是消息讀寫的通道。客戶端可以建立多個 channel,每個 channel 表示一個會話任務。

  4. message:消息,服務器和應用程序之間傳遞的數據,由 properties 和 body 組成。properties 可以對消息進行修飾,比如消息的優先級,延遲等高級特性;body 是消息實體內容。

  5. Virtual host:虛擬主機,用於邏輯隔離,最上層消息的路由。一個 Virtual host 可以若干個 Exchange 和 Queue,同一個 Virtual host 不能有同名的 Exchange 或 Queue。

  6. Exchange:交換機,接受消息,根據路由鍵轉發消息到綁定的隊列上。

  7. banding:Exchange 和 Queue 之間的虛擬連接,binding 中可以包括 routing key

  8. routing key:一個路由規則,虛擬機根據他來確定如何路由 一條消息。

  9. Queue:消息隊列,用來存放消息的隊列。

Exchange

交換機的類型,direct、topic、fanout、headers,durability(是否需要持久化 true 需要)auto delete 當最後一個綁定 Exchange 上的隊列被刪除 Exchange 也刪除。

  1. Direct Exchange, 所有發送到 Direct Exchange 的消息被轉發到 RouteKey 中指定的 Queue,Direct Exchange 可以使用默認的默認的 Exchange (default Exchange),默認的 Exchange 會綁定所有的隊列,所以 Direct 可以直接使用 Queue 名(作爲 routing key )綁定。或者消費者和生產者的 routing key 完全匹配。

  2. Toptic Exchange, 是指發送到 Topic Exchange 的消息被轉發到所有關心的 Routing key 中指定 topic 的 Queue 上。Exchange 將 routing key 和某 Topic 進行模糊匹配,此時隊列需要綁定一個 topic。所謂模糊匹配就是可以使用通配符,“#”可以匹配一個或多個詞,“”只匹配一個詞比如 “log.#” 可以匹配“log.info.test” "log." 就只能匹配 log.error。

  3. Fanout Exchange: 不處理路由鍵,只需簡單的將隊列綁定到交換機上。發送到改交換機上的消息都會被髮送到與該交換機綁定的隊列上。Fanout 轉發是最快的。

消息如何保證 100%投遞

什麼是生產端的可靠性投遞?
  1. 保證消息的成功發出

  2. 保證 MQ 節點節點的成功接收

  3. 發送端 MQ 節點(broker)收到消息確認應答

  4. 完善消息進行補償機制

可靠性投遞保障方案

消息落庫,對消息進行打標

消息的延遲投遞

在高併發場景下,每次進行 db 的操作都是每場消耗性能的。我們使用延遲隊列來減少一次數據庫的操作。

消息冪等性

冪等性是什麼?點擊這篇文章看下。

我對一個動作進行操作,我們肯能要執行 100 次 1000 次,對於這 1000 次執行的結果都必須一樣的。比如單線程方式下執行 update count-1 的操作執行一千次結果都是一樣的,所以這個更新操作就是一個冪等的,如果是在併發不做線程安全的處理的情況下 update 一千次操作結果可能就不是一樣的,所以併發情況下的 update 操作就不是一個冪等的操作。對應到消息隊列上來,就是我們即使受到了多條一樣的消息,也和消費一條消息效果是一樣的。

在公衆號頂級架構師後臺回覆 “offer”,獲取一份驚喜禮包。

高併發的情況下如何避免消息重複消費
  1. 唯一 id + 加指紋碼,利用數據庫主鍵去重。

    優點:實現簡單

    缺點:高併發下有數據寫入瓶頸。

  2. 利用 Redis 的原子性來實習。

    使用 Redis 進行冪等是需要考慮的問題

confirm 確認消息、Return 返回消息

理解 confirm 消息確認機制

如何實現 confirm 確認消息。
return 消息機制

Return 消息機制處理一些不可路由的消息,我們的生產者通過指定一個 Exchange 和 Routinkey,把消息送達到某一個隊列中去,然後我們消費者監聽隊列進行消費處理!

在某些情況下,如果我們在發送消息的時候當 Exchange 不存在或者指定的路由 key 路由找不到,這個時候如果我們需要監聽這種不可到達的消息,就要使用 Return Listener!

Mandatory 設置爲 true 則會監聽器會接受到路由不可達的消息,然後處理。如果設置爲 false,broker 將會自動刪除該消息。

消費端自定義監聽
消費端限流

什麼是消費端的限流?限流算法點擊這裏閱讀。

假設我們有個場景,首先,我們有個 rabbitMQ 服務器上有上萬條消息未消費,然後我們隨便打開一個消費者客戶端,會出現:巨量的消息瞬間推送過來,但是我們的消費端無法同時處理這麼多數據。

這時就會導致你的服務崩潰。其他情況也會出現問題,比如你的生產者與消費者能力不匹配,在高併發的情況下生產端產生大量消息,消費端無法消費那麼多消息。

void basicQOS(unit prefetchSize,ushort prefetchCount,Boolean global) 方法。

消費端 ack 與重回隊列
消息重回隊列
TTL 隊列 / 消息

TTL time to live 生存時間。

死信隊列

死信隊列:DLX,Dead-Letter-Exchange

利用 DLX,當消息在一個隊列中變成死信(dead message,就是沒有任何消費者消費)之後,他能被重新 publish 到另一個 Exchange,這個 Exchange 就是 DLX。

消息變爲死信的幾種情況:

  1. 消息被拒絕(basic.reject/basic.nack)同時 requeue=false(不重回隊列)

  2. TTL 過期

  3. 隊列達到最大長度

DLX 也是一個正常的 Exchange,和一般的 Exchange 沒有任何的區別,他能在任何的隊列上被指定,實際上就是設置某個隊列的屬性。

當這個隊列出現死信的時候,RabbitMQ 就會自動將這條消息重新發布到 Exchange 上去,進而被路由到另一個隊列。可以監聽這個隊列中的消息作相應的處理,這個特性可以彌補 rabbitMQ 以前支持的 immediate 參數的功能。

死信隊列的設置

Exchange: dlx.exchange(自定義的名字)

queue: dlx.queue(自定義的名字)

routingkey: #(# 表示任何 routingkey 出現死信都會被路由過來)

然後正常的聲明交換機、隊列、綁定,只是我們在隊列上加上一個參數:

arguments.put("x-dead-letter-exchange","dlx.exchange");

rabbitMQ 集羣模式

  1. 主備模式:實現 rabbitMQ 高可用集羣,一般在併發量和數據不大的情況下,這種模式好用簡單。又稱 warren 模式。(區別於主從模式,主從模式主節點提供寫操作,從節點提供讀操作,主備模式從節點不提供任何讀寫操作,只做備份)如果主節點宕機備份從節點會自動切換成主節點,提供服務。

  2. 集羣模式:經典方式就是 Mirror 模式,保證 100% 數據不丟失,實現起來也是比較簡單。

多活模式:這種模式也是實現異地數據複製的主流模式,因爲 shovel 模式配置相對複雜,所以一般來說實現異地集羣都是使用這種雙活,多活的模式,這種模式需要依賴 rabbitMQ 的 federation 插件,可以實現持續可靠的 AMQP 數據。

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

多活架構如下:

federation 插件是一個不需要構建 Cluster,而在 Brokers 之間傳輸消息的高性能插件,federation 可以在 brokers 或者 cluster 之間傳輸消息,連接的雙方可以使用不同的 users 或者 virtual host 雙方也可以使用不同版本的 erlang 或者 rabbitMQ 版本。federation 插件可以使用 AMQP 協議作爲通訊協議,可以接受不連續的傳輸。

Federation Exchanges, 可以看成 Downstream 從 Upstream 主動拉取消息,但  
並不是拉取所有消息,必須是在 Downstream 上已經明確定義 Bindings 關係的  
Exchange, 也就是有實際的物理 Queue 來接收消息,纔會從 Upstream 拉取消息  
到 Downstream。

使用 AMQP 協議實施代理間通信,Downstream 會將綁定關係組合在一起, 綁定 / 解除綁定命令將發送到 Upstream 交換機。

因此,Federation Exchange 只接收具有訂閱的消息。

HAProxy 是一款提供高可用性、負載均衡以及基於 TCP (第四層) 和 HTTP  
(第七層) 應用的代理軟件, 支持虛擬主機,它是免費、快速並且可靠的一種解決  
方案。

HAProxy 特別適用於那些負載特大的 web 站點,這些站點通常又需要會  
話保持或七層處理。HAProxy 運行在時下的硬件上,完全可以支持數以萬計的  
併發連接。

並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中  
同時可以保護你的 web 服務器不被暴露到網絡上。

HAProxy 性能爲何這麼好?
  1. 單進程、事件驅動模型顯著降低了. 上下文切換的開銷及內存佔用.

  2. 在任何可用的情況下,單緩衝 (single buffering) 機制能以不復制任何數據的方式完成讀寫操作,這會節約大量的 CPU 時鐘週期及內存帶寬

  3. 藉助於 Linux 2.6 (>= 2.6.27.19). 上的 splice() 系統調用,HAProxy 可以實現零複製轉發 (Zero-copy forwarding), 在 Linux 3.5 及以上的 OS 中還可以實現心零複製啓動 (zero-starting)

  4. 內存分配器在固定大小的內存池中可實現即時內存分配,這能夠顯著減少創建一個會話的時長

  5. 樹型存儲: 側重於使用作者多年前開發的彈性二叉樹,實現了以 O(log(N)) 的低開銷來保持計時器命令、保持運行隊列命令及管理輪詢及最少連接隊列

keepAlive

KeepAlived 軟件主要是通過 VRRP 協議實現高可用功能的。VRRP 是  
Virtual Router RedundancyProtocol(虛擬路由器冗餘協議) 的縮寫,  
VRRP 出現的目的就是爲了解決靜態路由單點故障問題的,它能夠保證當  
個別節點宕機時,整個網絡可以不間斷地運行所以,Keepalived - - 方面  
具有配置管理 LVS 的功能,同時還具有對 LVS 下面節點進行健康檢查的功  
能,另一方面也可實現系統網絡服務的高可用功能

keepAlive 的作用

  1. 管理 LVS 負載均衡軟件

  2. 實現 LVS 集羣節點的健康檢查中

  3. 作爲系統網絡服務的高可用性 (failover)

Keepalived 如何實現高可用

Keepalived 高可用服務對之間的故障切換轉移,是通過 VRRP (Virtual Router  
Redundancy Protocol , 虛擬路由器冗餘協議) 來實現的。

在 Keepalived 服務正常工作時,主 Master 節點會不斷地向備節點發送 (多播的方式) 心跳消息,用以告訴備 Backup 節點自己還活看,當主 Master 節點發生故障時,就無法發送心跳消息,備節點也就因此無法繼續檢測到來自主 Master 節點的心跳了,於是調用自身的接管程序,接管主 Master 節點的 IP 資源及服務。

而當主 Master 節點恢復時備 Backup 節點又會釋放主節點故障時自身接管的 IP 資源及服務,恢復到原來的備用角色。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/V5vlXmqQY21GqAJC_bjXbQ