消息隊列
基本概念
定義
消息隊列(Message Queue, MQ)是一種分布式中間件,通過異步通信、消息暫存和解耦生產消費雙方的機制,提供消息的順序性保證、可靠投遞和流量控制能力,廣泛應用于微服務解耦、大數據流處理等場景。
核心組件
生產者 producer:消息的生產者,負責發送消息。
消費者 consumer:消息的消費者,訂閱并處理消息。
消費者組 consumer group:所有消費者都屬于某一消費者組,同一個消費者組內的消費者共同消費同一類型的消息,實現消費性能的擴展。
租戶 tenant:邏輯概念,是資源歸屬和權限控制的基本單位。
集群 cluster:一組節點的集合。
Broker:用于存儲和轉發消息的物理節點。
主題 topic:邏輯概念,同一種業務類型的消息的集合。
偏移量 offset:消息的唯一標識,由消費者返回,記錄目前消費的位置。
消息模型
點對點:消息被單個消費者消費,如訂單處理。
發布/訂閱:消息廣播給多個消費者,如新聞推送。
核心功能
功能 | 說明 |
服務解耦 | 解除多個業務系統之間的耦合度,減少系統之間影響 |
異步通信 | 生產者和消費者無需同時在線,通過消息隊列暫存消息實現異步通信 |
流量控制 | 削峰填谷,突發流量被隊列緩沖,避免壓垮下游系統 |
順序收發 | 先進先出,保證消息的順序性(全局有序或分區有序) |
零拷貝 | 通過 OS 和硬件協作,減少數據在內存中的冗余復制,實現高吞吐 |
消息回溯 | 重置?offset 到指定位置,重新消費歷史消息 |
應用場景
大數據流處理:實時數據處理與 ETL
金融:支付對賬、交易流水
物聯網:設備指令下發、狀態上報
微服務:服務 A 通過 MQ 通知服務 B,避免直接 HTTP 調用帶來的耦合和超時風險
Kafka
架構設計
1.??生產者從 ZooKeeper* 獲取 Topic 的元數據(如 Partition Leader 的位置)后,以 push 模式發布消息到對應的 broker 上。
2.??每條消息都屬于一個 Topic,每個 Topic 分為多個 Partition 分區,物理上由多個日志分片 Segment 文件組成。每個 Partition 都有多個副本,被存儲在不同的 Brokers 上。消息發送到 Leader 后,會同步到 Follower 以確保冗余。
3.??消費者以 pull 模式從 Leader 主副本里拉取消息,返回 offset 值用于記錄現在消費的位置。
* ZooKeeper 的核心作用
功能 | 說明 |
Broker 注冊 | Broker 啟動時向 ZooKeeper 注冊自己的地址和 Partition 分配情況 |
Leader 選舉 | 當 Leader Partition 宕機時,協助選舉新的 Leader |
Topic 配置管理 | 存儲 Topic 的 Partition 數量、副本因子等元數據 |
功能原理
1.??持久化:消息存儲在 broker 磁盤中,被消費后不會立即被刪除
2.??高吞吐:單個 partition 批處理,多個 partition 并行處理
3.??高擴展:topic 分區化,存儲在不同 brokers 中
4.??容災和高可用:每個 partition 都有多個副本,ISR 確保副本之間的同步
5.??低延遲:稀疏索引和二分查找
RocketMQ
架構設計
1.??生產者向 NameServer 查詢 Topic 的路由信息,選擇目標 MessageQueue。
2.??發送消息到對應的 Master Broker,同步到 Slave。
3.??消費者從 NameServer 獲取 Topic 的路由信息,從 Master Broker 拉取消息,定期提交 Offset 到 Broker。
功能原理
1.??金融級可靠
同步刷盤 | 所有消息先寫入磁盤后才返回 ACK,確保數據不丟失 |
主從同步復制 | 消息必須同步到 Slave 節點后才響應生產者,避免主節點宕機丟數據 |
Broker 主從切換 | Master 故障時,Slave 自動提升為新 Master |
多副本 | 支持多副本,數據分布在不同物理機/機架 |
嚴格的順序性 | 同一隊列的消息嚴格 FIFO,適用于金融交易(如訂單狀態變更) |
死信隊列 | 處理失敗的消息自動進入 DLQ,避免阻塞正常流程 |
2.??事務消息:兩階段提交
-?生產者發送一條對消費者不可見的半消息(Half Message)到 Broker,Broker 持久化該消息,但不會將其投遞給消費者。
-?生產者執行本地數據庫操作后,根據本地事務結果,向 Broker 發送 Commit 或 Rollback 指令。
-?僅當收到 Commit 后,Broker 才將消息標記為可消費,后續推送給消費者,以確保本地數據庫事務和消息發送兩個操作的原子性。
3.??消息過濾:基于 tag 或 sql 語句進行過濾,在服務端將符合條件的消息投遞給消費者。
Pulsar
產品架構設計
* Segment 即 BookKeeper 的 Ledger,是一種 append-only 的日志文件
1.??生產者查詢 Topic 路由,將消息發送到對應的 Broker
2.??消息被拆分為多個 Segment,broker 將消息寫到多個 bookie 中持久化存儲。(同一個 partition 的 segment 分散在多個 bookie,支持多個 bookie 并行讀取。)
3.??消費者請求消息,broker 從 bookie 中拉取消息并轉發給消費者
功能原理
1.??計算(Broker)與存儲(Bookie)分離:
- broker:無狀態的 proxy 服務,負責接收消息、傳遞消息、集群負載均衡等操作。
-?bookie:有狀態,負責持久化存儲消息。
2.??故障隔離:Broker 崩潰不影響數據,Bookie 故障自動從其他副本重建恢復。
3.??彈性擴展:Broker 無需考慮數據遷移,可快速水平擴縮容;Bookie 存儲層可按需獨立擴展,新增 Bookie 后,數據自動重新分布。
MQ 系列對比
產品 | Kafka | RocketMQ | Pulsar |
產品特性 | 高并發、高吞吐、實時流處理平臺 | 低延遲、高可靠、強一致 | 云原生、存算分離、跨地域復制 |
應用場景 | 對吞吐要求高的離線場景 | 對可靠性要求高的在線業務場景 | 兼容在線和離線請求 |
適用業務 | ? 網頁活動追蹤 ? 日志分析、監控采集 ? 流數據集成 | ? 電商在線支付、直播 ? 證券交易 ? 金融對賬 | ? 跨云/跨地域數據同步 ? IoT 設備管理與監控 ? Serverless 事件驅動 |
broker | 存儲數據,處理消息請求 | 存儲數據,處理消息請求 | 無狀態的服務,不存儲數據,只負責消息的路由和處理 |
數據存儲單位 | Partition | CommitLog(唯一物理存儲文件,完全順序寫入) | Segment(顆粒更小,更利于存儲負載均衡) |
數據一致性 | 依賴 ISR 機制 | 同步刷盤 + 主從同步 | BookKeeper 支持同步復制 |
擴展性 | 通過增加 Partition 數量,擴容 Broker 需要 rebalance | 通過增加 Broker 組擴展 Queue 數量 | Broker/Bookie 獨立按需擴展計算/存儲 |
故障切換 | 依賴 Controller 選舉新 Leader | 組內 Slave 接管 Master,無需數據遷移立即接管 | ? Broker 崩潰后,新節點無需數據遷移立即接管 ? Bookie 節點故障時,數據自動從其他副本重建 |
常見問題
為什么需要消息隊列?
首先要知道什么是消息隊列:消息隊列通過解耦生產與消費者來實現消息異步、流量控制等功能。
那么什么是生產者/消費者:生產者通常是業務動作的發起者,生產需要被傳遞或處理的業務數據,可以是訂單系統、支付系統、傳感器設備等;而消費者通常是下游服務或數據分析模塊,比如庫存系統、Spark 作業等。
為什么需要解耦生產者和消費者:消息隊列產品的主要作用就是轉儲日志、監控數據等,舉個例子就像豐巢快遞柜,快遞員若是不能把快遞及時送到人員手上會造成快遞擁堵,效率減慢;但是有豐巢柜來存儲后就可以有一個地方暫存,消費者需要消費的時候再去拿快遞,拉消息一樣的道理。通過消息隊列,業務系統可以做到故障隔離(生產者宕機不影響消費者)彈性擴展(應對流量波動),真正實現“高內聚、低耦合”的業務架構。
為什么叫消息隊列為集群?
集群是一組節點的集合,節點可以是物理機或虛擬機。消息隊列產品采用了分布式架構設計,通過多節點協作實現高可用、高性能和可擴展性(具體參見上面的架構設計圖)。
命名空間是做什么的?
命名空間能在多租戶之間實現邏輯隔離。
首先要理解多租戶的概念,多租戶就是多個用戶共享一個集群。消息隊列產品通過命名空間和角色權限的配合來實現權限管控,從而實現不同命名空間之間的邏輯隔離。具體來講就是為用戶(角色)配置某個命名空間內的讀寫權限,一個命名空間里的所有 topic?都繼承相同的設置,則用戶只對該命名空間內的 topic 有操作權限。可以參考下圖幫助理解:
如何理解 topic 這個概念?
在學習消息隊列產品的過程中,要注意區分邏輯概念和物理概念。像 topic 和 partition 都是業務上的邏輯概念,實際上最后消息都是以一個個 segment 文件的形式存儲在物理機器上。
topic?代表了消息的類別或主題,是生產消費的最小單位。從業務層面來講,topic?就像是一個消息的分類標簽,生產者將相關的消息發送到特定的?topic?中,而消費者則通過訂閱感興趣的?topic?來獲取和處理這些消息。這種設計使得不同業務領域的消息能夠自然地隔離,比如訂單系統的消息可以發布到"order_topic",而支付系統的消息則流向"payment_topic",從而實現業務邏輯的清晰劃分。
topic 的設計還體現了消息隊列的關鍵特性——發布/訂閱模式。生產者不需要知道有哪些消費者存在,只需關注將消息發送到正確的 topic;同樣,消費者也只需訂閱自己關心的 topic,無需感知消息的生產者是誰。這種松耦合的架構使得系統各組件能夠獨立演化,大大提升了整體架構的靈活性。此外,通過 topic 可以實現消息的多播,即一條消息可以被多個消費者組同時消費,這在需要將同一數據用于不同業務場景時顯得尤為重要。
什么是數據落盤?
計算機存儲分為磁盤、內存和緩存等。
消息隊列將接收到的數據寫入磁盤持久化存儲的過程叫做落盤,比如消息存儲到 kafka 和 rocketmq 的 broker 以及 pulsar 的 bookie 的磁盤上這個過程。
具體實現上,kafka 是將消息先寫入 Page Cache(內存緩沖),再異步刷盤(可配置同步刷盤),RocketMQ 支持同步刷盤(每條消息立即寫入磁盤)或異步刷盤(批量寫入)。
消息隊列如何保證數據的一致性?
kafka 通過 ISR(In-Sync Replicas)機制來維護數據一致性。當生產者發送消息時,Leader 副本會先將消息寫入本地日志,然后要求所有 ISR 中的 Follower 副本完成同步復制后,這條消息才會被確認為已提交。
RocketMQ 采用了雙重保障機制來維護數據一致性。首先是同步刷盤策略,當 Broker 接收到消息后,可以選擇立即將消息寫入磁盤(同步刷盤)而非僅保留在內存中。其次是主從同步機制,每個主節點都會將消息同步到其從節點,只有當主從都成功寫入后才會向生產者返回確認響應。
Pulsar 依賴 BookKeeper 作為底層存儲引擎,每條消息都會被同步復制到多個 Bookie 節點,只有當大多數節點確認寫入后,這條消息才會被標記為持久化成功。
參考鏈接
Apache Kafka
RocketMQ · 官方網站 | RocketMQ 消息隊列
Apache Pulsar | Apache Pulsar
https://zhuanlan.zhihu.com/p/103249714