消息隊列的 6 種經典使用場景和 Kafka 架構設計原理詳細解析

我是碼哥,可以叫我靚仔。今天來聊一聊 Kafka 消息隊列的使用場景和核心架構實現原理,幫助你全面瞭解 Kafka 其內部工作原理和設計理念。。

Apache Kafka 是一個高吞吐量、分佈式的流處理平臺,廣泛應用於實時數據管道和流處理應用中。

Kafka 以其高性能、低延遲、擴展性和可靠性,成爲了大數據生態系統中的重要組件。

  1. 消息隊列有什麼作用

消息隊列是一種進程間通信或者同一個進程中不同線程間的通信方式,主要解決異步處理、應用耦合、流量消峯、負載均衡等問題,實現高性能、高可用、可伸縮和最終一致性架構,是大型分佈式系統不可缺少的中間件。

kafka 本質也是一個消息隊列,如下圖,上游系統將消息發送到消息中間件,下游系統從消息中間件中獲取消息消費。

馬樓:“上游系統爲什麼不直接發消息給下游系統,搞箇中間商幹啥?”

這就要從消息隊列的主要作用說起了。

異步處理

消息隊列可以實現異步通信,使得發送消息的組件不需要等待接收消息的組件處理完畢,從而提高系統的響應速度和處理效率。

如下圖所示,阿斗被邀請去休閒養生 SPA 享受,服務包含泡腳、按摩、喫水果、看電視。

SPA 系統只需要驗證啊斗的會員卡有錢就也可以服務了,串行化執行的每個步驟的話,體驗太差。可以同時進行,快樂加倍。泡腳、按摩的同時可以同時喫水果看電視,大大提升體驗。

應用解耦

如下圖所示,採用了消息中間件之後,訂單系統將下單消息發送到 MQ 存儲,然後各個下游系統從 MQ 中獲取消息並執行對應的業務邏輯。

這種異步的方式,減少了服務之間的耦合程度,不然的話,維護訂單系統的馬樓要哭死,下單後調用多個下游系統,有的系統通過接口調用還必須要求重試機制不能丟失。

有了消息隊列後,利用 MQ 本身提供的高可用保證數據不丟失,另外不管你是王啓年還是範閒,我就放到消息隊列中,你們自己從 MQ 拿,不用再去聯繫每個系統的維護人員。

流量削峯

在流量高峯期,消息隊列可以充當緩衝區,平滑高峯流量,避免系統因瞬時高負載而崩潰。

比如某個接口平時的流量也就 100TPS,特殊時刻會暴增,達到 4000 TPS,一般來說,MySQL 每秒可以處理 2000 個請求,每秒 4000 個請求,可能直接把 MySQL 搞崩潰。

你可以通過消息隊列來進行流量削峯,防止把 MySQL 幹爆,引入 MQ 後,先將請求存到 MQ 中,MySQL 慢慢處理請求。

負載均衡

Kafka 的 Topic 可以分成多個 Partition,每個 Paritition 類似於一個隊列,單個 Paritition 可以保證數據有序。

Kafka 具有優秀的分區分配算法——StickyAssignor,把生產者的消息發送到不同 Paritition,保證 Paritition 的分配儘量地均衡。這樣,整個集羣的分區儘量地均衡,各個 Broker 和 Consumer 的處理不至於出現太大的傾斜。

同一個 Consumer Group 下的 Consumer 併發消費 Paritition,需要注意的是,如果 Consumer Group 下的 Consumer 個數超過 Partition 數量,那麼會出現空閒 Consumer。

順序保證

每個 Kafka 主題(Topic)可以分爲多個分區(Partition)。每個分區都是一個有序的、不可變的消息隊列。

生產者(Producer)將消息發送到分區時,Kafka 按消息的發送順序將其追加到分區的末尾。

消費者(Consumer)讀取分區中的消息時,也是按照消息的存儲順序逐條讀取。

因此,在同一個分區內,消息的順序是嚴格保證的。這對於某些業務場景來說非常重要,特別是需要保證消息順序性的應用,例如金融交易、訂單處理等。

針對消息有序的業務需求,還分爲全局有序和局部有序。

全局有序

Kafka 的一個 Topic 可分爲多個 Partition,Producer 發送消息的時候,kafka 會使用負載均衡策略將消息發送到其中一個 Partition,會導致順序是亂的。

**要保證全局有序,那麼一個 Topic 只能存在一個 Partition。**而且對應的 Consumer 也要使用單線程或者保證消費順序的線程模型。

局部有序

要滿足局部有序,只需要在發消息的時候指定 Partition Key,Kafka 對其進行 Hash 計算,根據計算結果決定放入哪個 Partition。這樣 Partition Key 相同的消息會放在同一個 Partition,從而保證有序。

此時,Partition 的數量仍然可以設置多個,提升 Topic 的整體吞吐量。

容錯性

Kafka 提供了消息持久化、重試機制和確認機制,確保消息不會丟失或重複處理,增強系統的容錯能力。

  1. Kafka 核心組件

終於到今天的主角登場,直接上圖。

Kafka 的核心架構由以下幾個主要組件組成:

  1. Producer(生產者):發送消息的一方,負責發佈消息到 Kafka 主題(Topic)。

  2. Consumer(消費者):接受消息的一方,訂閱主題並處理消息。

  3. Broker(代理):服務代理節點,Kafka 集羣中的一臺服務器就是一個 broker,可以水平無限擴展,同一個 Topic 的消息可以分佈在多個 broker 中。

  4. Topic(主題):Kafka 中的消息以 Topic 爲單位進行劃分,生產者將消息發送到特定的 Topic,而消費者負責訂閱 Topic 的消息並進行消費。

  5. Partition(分區):主題的物理分片,提高了並行處理能力。

  6. Replica(副本):副本,是 Kafka 保證數據高可用的方式,Kafka 同一 Partition 的數據可以在多 Broker 上存在多個副本,通常只有主副本對外提供讀寫服務,當主副本所在 broker 崩潰或發生網絡一場,Kafka 會在 Controller 的管理下會重新選擇新的 Leader 副本對外提供讀寫服務。

  7. ZooKeeper:管理 Kafka 集羣的元數據和分佈式協調。

  8. Topic 和 Partition


來看下什麼是 Topic 和 Partition。

3.1 主題(Topic)

Topic 是 Kafka 中數據的邏輯分類單元,可以理解成一個隊列。Broker 是所有隊列部署的機器,Producer 將消息發送到特定的 Topic,而 Consumer 則從特定的 Topic 中消費消息。

3.2 分區(Partition)

爲了提高並行處理能力和擴展性,Kafka 將一個 Topic 分爲多個 Partition。

每個 Partition 是一個有序的消息隊列,消息在 Partition 內部是有序的,但在不同的 Partition 之間沒有順序保證。

Producer 可以並行地將消息發送到不同的 Partition,Consumer 也可以並行地消費不同的 Partition,從而提升整體處理能力。

3.3 副本(Replica)

每個 Partition 可以有多個副本(Replica),分佈在不同的 Broker 上。

Kafka 會爲分區的多個副本選舉一個作爲主副本 (Leader),主副本對外提供讀寫服務,從副本(Follower) 實時同步 Leader 的數據。

Kafka 通過副本機制實現高可用性,當一個 Broker 故障時,可以通過副本保證數據不丟失,並繼續提供服務。

如下圖所示,黃色表示 leader,灰色表示 follower。Topic 分了三個 Patition,副本數是 2。

  1. Consumer 和 ConsumerGroup

Kafka 有消費組的概念,每個消費者只能消費所分配到的分區的消息,每一個分區只能被一個消費組中的一個消費者所消費,所以同一個消費組中消費者的數量如果超過了分區的數量,將會出現有些消費者分配不到消費的分區。消費組與消費者關係如下圖所示:

  1. 數據存儲機制

Kafka 的數據存儲機制採用了順序寫入磁盤的方式,通過這種方式來提高寫入性能。

每個 Partition 的消息被存儲在多個 Segment 文件中,每個 Segment 文件由一組連續的消息組成。Segment 文件通過索引和日誌文件進行管理,索引文件記錄了每條消息在日誌文件中的偏移量。

Kafka 的存儲機制具備以下幾個特點:

  1. 順序寫入:Kafka 通過順序寫入來提高寫入速度和磁盤利用率。

  2. Segment 文件:消息被分段存儲,便於管理和清理。

  3. 索引機制:通過索引快速定位消息,提高讀取效率。

  4. 日誌清理策略:支持基於時間和大小的日誌清理策略,確保存儲空間的有效利用。

  1. 高可用性和容錯機制

Kafka 通過以下幾種機制來實現高可用性和容錯性:

  1. 副本機制:每個 Partition 有多個副本,主副本(Leader)負責讀寫操作,其它副本(Follower)定期從 Leader 同步數據。當 Leader 發生故障時,會從 Follower 中選舉新的 Leader。

  2. ACK 機制:Producer 發送消息時,可以通過設置 ACK 來確保消息被成功寫入 Leader 和 Follower,從而保證數據不丟失。

  3. ISR(In-Sync Replica)機制:Kafka 維護一個 ISR 列表,記錄當前與 Leader 保持同步的副本。只有在 ISR 列表中的副本纔會參與 Leader 選舉。

  4. ZooKeeper 協調:Kafka 使用 ZooKeeper 進行分佈式協調,管理元數據和集羣狀態。ZooKeeper 負責管理 Broker 的註冊信息、Topic 和 Partition 的元數據以及 Leader 選舉等。

  5. 消息傳遞保證


Kafka 提供了三種消息傳遞保證:

  1. At most once:消息最多傳遞一次,可能丟失。

  2. At least once:消息至少傳遞一次,可能重複。

  3. Exactly once:消息準確傳遞一次,Kafka 在 0.11.0.0 版本引入了事務機制,支持端到端的精確一次語義。

  4. ZooKeeper 的作用


Kafka 將 Broker、Topic 和 Partition 的元數據信息存儲在 Zookeeper 上。通過在 Zookeeper 上建立相應的數據節點,並監聽節點的變化,Kafka 使用 Zookeeper 完成以下功能:

  1. 元數據管理:存儲 Kafka 的元數據,包括 Broker 列表、Topic 和 Partition 信息、ISR 列表等。

  2. 分佈式協調:負責 Broker 的註冊和發現、Leader 選舉、負載均衡等。

  3. 狀態監控:監控 Kafka 集羣的運行狀態,保證系統的一致性和高可用性。

  1. Kafka 的擴展性

Kafka 的擴展性主要體現在以下幾個方面:

  1. 水平擴展:通過增加 Broker 節點,可以輕鬆擴展 Kafka 集羣的存儲和處理能力。

  2. Partition 擴展:通過增加 Partition 數量,可以提高 Topic 的並行處理能力。

  3. 動態配置:Kafka 支持在運行時動態調整部分配置,如 Topic 的分區數量和副本因子等。

博主簡介

碼哥,9 年互聯網公司後端工作經驗,InfoQ 簽約作者、51CTO Top 紅人,阿里雲開發者社區專家博主,目前擔任後端架構師主責,擅長 Redis、Spring、Kafka、MySQL 技術和雲原生微服務。

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