消息隊列的六種經(jīng)典使用場景和 Kafka 架構(gòu)設(shè)計原理詳細(xì)解析
我是碼哥,可以叫我靚仔。今天來聊一聊 Kafka 消息隊列的使用場景和核心架構(gòu)實現(xiàn)原理,幫助你全面了解 Kafka 其內(nèi)部工作原理和設(shè)計理念。。
Apache Kafka 是一個高吞吐量、分布式的流處理平臺,廣泛應(yīng)用于實時數(shù)據(jù)管道和流處理應(yīng)用中。
Kafka 以其高性能、低延遲、擴展性和可靠性,成為了大數(shù)據(jù)生態(tài)系統(tǒng)中的重要組件。
1.消息隊列有什么作用
消息隊列是一種進(jìn)程間通信或者同一個進(jìn)程中不同線程間的通信方式,主要解決異步處理、應(yīng)用耦合、流量消峰、負(fù)載均衡等問題,實現(xiàn)高性能、高可用、可伸縮和最終一致性架構(gòu),是大型分布式系統(tǒng)不可缺少的中間件。
kafka 本質(zhì)也是一個消息隊列,如下圖,上游系統(tǒng)將消息發(fā)送到消息中間件,下游系統(tǒng)從消息中間件中獲取消息消費。
馬樓:“上游系統(tǒng)為什么不直接發(fā)消息給下游系統(tǒng),搞個中間商干啥?”
這就要從消息隊列的主要作用說起了。
異步處理
消息隊列可以實現(xiàn)異步通信,使得發(fā)送消息的組件不需要等待接收消息的組件處理完畢,從而提高系統(tǒng)的響應(yīng)速度和處理效率。
如下圖所示,阿斗被邀請去休閑養(yǎng)生 SPA 享受,服務(wù)包含泡腳、按摩、吃水果、看電視。
SPA 系統(tǒng)只需要驗證啊斗的會員卡有錢就也可以服務(wù)了,串行化執(zhí)行的每個步驟的話,體驗太差。可以同時進(jìn)行,快樂加倍。泡腳、按摩的同時可以同時吃水果看電視,大大提升體驗。
應(yīng)用解耦
如下圖所示,采用了消息中間件之后,訂單系統(tǒng)將下單消息發(fā)送到 MQ 存儲,然后各個下游系統(tǒng)從 MQ 中獲取消息并執(zhí)行對應(yīng)的業(yè)務(wù)邏輯。
這種異步的方式,減少了服務(wù)之間的耦合程度,不然的話,維護(hù)訂單系統(tǒng)的馬樓要哭死,下單后調(diào)用多個下游系統(tǒng),有的系統(tǒng)通過接口調(diào)用還必須要求重試機制不能丟失。
有了消息隊列后,利用 MQ 本身提供的高可用保證數(shù)據(jù)不丟失,另外不管你是王啟年還是范閑,我就放到消息隊列中,你們自己從 MQ 拿,不用再去聯(lián)系每個系統(tǒng)的維護(hù)人員。
流量削峰
在流量高峰期,消息隊列可以充當(dāng)緩沖區(qū),平滑高峰流量,避免系統(tǒng)因瞬時高負(fù)載而崩潰。
比如某個接口平時的流量也就 100TPS,特殊時刻會暴增,達(dá)到 4000 TPS,一般來說,MySQL 每秒可以處理 2000 個請求,每秒 4000 個請求,可能直接把 MySQL 搞崩潰。
你可以通過消息隊列來進(jìn)行流量削峰,防止把 MySQL 干爆,引入 MQ 后,先將請求存到 MQ 中,MySQL 慢慢處理請求。
負(fù)載均衡
Kafka 的 Topic 可以分成多個 Partition,每個 Paritition 類似于一個隊列,單個 Paritition 可以保證數(shù)據(jù)有序。
Kafka 具有優(yōu)秀的分區(qū)分配算法——StickyAssignor,把生產(chǎn)者的消息發(fā)送到不同 Paritition,保證 Paritition 的分配盡量地均衡。這樣,整個集群的分區(qū)盡量地均衡,各個 Broker 和 Consumer 的處理不至于出現(xiàn)太大的傾斜。
同一個 Consumer Group 下的 Consumer 并發(fā)消費 Paritition,需要注意的是,如果 Consumer Group 下的 Consumer 個數(shù)超過 Partition 數(shù)量,那么會出現(xiàn)空閑 Consumer。
順序保證
每個 Kafka 主題(Topic)可以分為多個分區(qū)(Partition)。每個分區(qū)都是一個有序的、不可變的消息隊列。
生產(chǎn)者(Producer)將消息發(fā)送到分區(qū)時,Kafka 按消息的發(fā)送順序?qū)⑵渥芳拥椒謪^(qū)的末尾。
消費者(Consumer)讀取分區(qū)中的消息時,也是按照消息的存儲順序逐條讀取。
因此,在同一個分區(qū)內(nèi),消息的順序是嚴(yán)格保證的。這對于某些業(yè)務(wù)場景來說非常重要,特別是需要保證消息順序性的應(yīng)用,例如金融交易、訂單處理等。
針對消息有序的業(yè)務(wù)需求,還分為全局有序和局部有序。
- 全局有序:一個 Topic 下的所有消息都需要按照生產(chǎn)順序消費。
- 局部有序:一個 Topic 下的消息,只需要滿足同一業(yè)務(wù)字段的要按照生產(chǎn)順序消費。例如:Topic 消息是訂單的流水表,包含訂單 orderId,業(yè)務(wù)要求同一個 orderId 的消息需要按照生產(chǎn)順序進(jìn)行消費。
全局有序
Kafka 的一個 Topic 可分為多個 Partition,Producer 發(fā)送消息的時候,kafka 會使用負(fù)載均衡策略將消息發(fā)送到其中一個 Partition,會導(dǎo)致順序是亂的。
要保證全局有序,那么一個 Topic 只能存在一個 Partition。而且對應(yīng)的 Consumer 也要使用單線程或者保證消費順序的線程模型。
局部有序
要滿足局部有序,只需要在發(fā)消息的時候指定 Partition Key,Kafka 對其進(jìn)行 Hash 計算,根據(jù)計算結(jié)果決定放入哪個 Partition。這樣 Partition Key 相同的消息會放在同一個 Partition,從而保證有序。
此時,Partition 的數(shù)量仍然可以設(shè)置多個,提升 Topic 的整體吞吐量。
容錯性
Kafka 提供了消息持久化、重試機制和確認(rèn)機制,確保消息不會丟失或重復(fù)處理,增強系統(tǒng)的容錯能力。
2. Kafka 核心組件
終于到今天的主角登場,直接上圖。
Kafka 的核心架構(gòu)由以下幾個主要組件組成:
- Producer(生產(chǎn)者):發(fā)送消息的一方,負(fù)責(zé)發(fā)布消息到 Kafka 主題(Topic)。
- Consumer(消費者):接受消息的一方,訂閱主題并處理消息。
- Broker(代理):服務(wù)代理節(jié)點,Kafka 集群中的一臺服務(wù)器就是一個 broker,可以水平無限擴展,同一個 Topic 的消息可以分布在多個 broker 中。
- Topic(主題):Kafka 中的消息以 Topic 為單位進(jìn)行劃分,生產(chǎn)者將消息發(fā)送到特定的 Topic,而消費者負(fù)責(zé)訂閱 Topic 的消息并進(jìn)行消費。
- Partition(分區(qū)):主題的物理分片,提高了并行處理能力。
- Replica(副本):副本,是 Kafka 保證數(shù)據(jù)高可用的方式,Kafka 同一 Partition 的數(shù)據(jù)可以在多 Broker 上存在多個副本,通常只有主副本對外提供讀寫服務(wù),當(dāng)主副本所在 broker 崩潰或發(fā)生網(wǎng)絡(luò)一場,Kafka 會在 Controller 的管理下會重新選擇新的 Leader 副本對外提供讀寫服務(wù)。
- ZooKeeper:管理 Kafka 集群的元數(shù)據(jù)和分布式協(xié)調(diào)。
3. Topic 和 Partition
來看下什么是 Topic 和 Partition。
(1)主題(Topic)
Topic 是 Kafka 中數(shù)據(jù)的邏輯分類單元,可以理解成一個隊列。Broker 是所有隊列部署的機器,Producer 將消息發(fā)送到特定的 Topic,而 Consumer 則從特定的 Topic 中消費消息。
(2)分區(qū)(Partition)
為了提高并行處理能力和擴展性,Kafka 將一個 Topic 分為多個 Partition。
每個 Partition 是一個有序的消息隊列,消息在 Partition 內(nèi)部是有序的,但在不同的 Partition 之間沒有順序保證。
Producer 可以并行地將消息發(fā)送到不同的 Partition,Consumer 也可以并行地消費不同的 Partition,從而提升整體處理能力。
(3)副本(Replica)
每個 Partition 可以有多個副本(Replica),分布在不同的 Broker 上。
Kafka 會為分區(qū)的多個副本選舉一個作為主副本(Leader),主副本對外提供讀寫服務(wù),從副本(Follower)實時同步 Leader 的數(shù)據(jù)。
Kafka 通過副本機制實現(xiàn)高可用性,當(dāng)一個 Broker 故障時,可以通過副本保證數(shù)據(jù)不丟失,并繼續(xù)提供服務(wù)。
如下圖所示,黃色表示 leader,灰色表示 follower。Topic 分了三個 Patition,副本數(shù)是 2。
4. Consumer 和 ConsumerGroup
Kafka 有消費組的概念,每個消費者只能消費所分配到的分區(qū)的消息,每一個分區(qū)只能被一個消費組中的一個消費者所消費,所以同一個消費組中消費者的數(shù)量如果超過了分區(qū)的數(shù)量,將會出現(xiàn)有些消費者分配不到消費的分區(qū)。消費組與消費者關(guān)系如下圖所示:
5. 數(shù)據(jù)存儲機制
Kafka 的數(shù)據(jù)存儲機制采用了順序?qū)懭氪疟P的方式,通過這種方式來提高寫入性能。
每個 Partition 的消息被存儲在多個 Segment 文件中,每個 Segment 文件由一組連續(xù)的消息組成。Segment 文件通過索引和日志文件進(jìn)行管理,索引文件記錄了每條消息在日志文件中的偏移量。
Kafka 的存儲機制具備以下幾個特點:
- 順序?qū)懭?/strong>:Kafka 通過順序?qū)懭雭硖岣邔懭胨俣群痛疟P利用率。
- Segment 文件:消息被分段存儲,便于管理和清理。
- 索引機制:通過索引快速定位消息,提高讀取效率。
- 日志清理策略:支持基于時間和大小的日志清理策略,確保存儲空間的有效利用。
6. 高可用性和容錯機制
Kafka 通過以下幾種機制來實現(xiàn)高可用性和容錯性:
- 副本機制:每個 Partition 有多個副本,主副本(Leader)負(fù)責(zé)讀寫操作,其它副本(Follower)定期從 Leader 同步數(shù)據(jù)。當(dāng) Leader 發(fā)生故障時,會從 Follower 中選舉新的 Leader。
- ACK 機制:Producer 發(fā)送消息時,可以通過設(shè)置 ACK 來確保消息被成功寫入 Leader 和 Follower,從而保證數(shù)據(jù)不丟失。
- ISR(In-Sync Replica)機制:Kafka 維護(hù)一個 ISR 列表,記錄當(dāng)前與 Leader 保持同步的副本。只有在 ISR 列表中的副本才會參與 Leader 選舉。
- ZooKeeper 協(xié)調(diào):Kafka 使用 ZooKeeper 進(jìn)行分布式協(xié)調(diào),管理元數(shù)據(jù)和集群狀態(tài)。ZooKeeper 負(fù)責(zé)管理 Broker 的注冊信息、Topic 和 Partition 的元數(shù)據(jù)以及 Leader 選舉等。
7. 消息傳遞保證
Kafka 提供了三種消息傳遞保證:
- At most once:消息最多傳遞一次,可能丟失。
- At least once:消息至少傳遞一次,可能重復(fù)。
- Exactly once:消息準(zhǔn)確傳遞一次,Kafka 在 0.11.0.0 版本引入了事務(wù)機制,支持端到端的精確一次語義。
8. ZooKeeper 的作用
Kafka 將 Broker、Topic 和 Partition 的元數(shù)據(jù)信息存儲在 Zookeeper 上。通過在 Zookeeper 上建立相應(yīng)的數(shù)據(jù)節(jié)點,并監(jiān)聽節(jié)點的變化,Kafka 使用 Zookeeper 完成以下功能:
- 元數(shù)據(jù)管理:存儲 Kafka 的元數(shù)據(jù),包括 Broker 列表、Topic 和 Partition 信息、ISR 列表等。
- 分布式協(xié)調(diào):負(fù)責(zé) Broker 的注冊和發(fā)現(xiàn)、Leader 選舉、負(fù)載均衡等。
- 狀態(tài)監(jiān)控:監(jiān)控 Kafka 集群的運行狀態(tài),保證系統(tǒng)的一致性和高可用性。
- Broker 注冊:Broker 是分布式部署并且之間相互獨立,Zookeeper 用來管理注冊到集群的所有 Broker 節(jié)點。
- Topic 注冊:在 Kafka 中,同一個 Topic 的消息會被分成多個分區(qū)并將其分布在多個 Broker 上,這些分區(qū)信息及與 Broker 的對應(yīng)關(guān)系也都是由 Zookeeper 在維護(hù)
- 生產(chǎn)者負(fù)載均衡:由于同一個 Topic 消息會被分區(qū)并將其分布在多個 Broker 上,因此,生產(chǎn)者需要將消息合理地發(fā)送到這些分布式的 Broker 上。
- 消費者負(fù)載均衡:與生產(chǎn)者類似,Kafka 中的消費者同樣需要進(jìn)行負(fù)載均衡來實現(xiàn)多個消費者合理地從對應(yīng)的 Broker 服務(wù)器上接收消息,每個消費者分組包含若干消費者,每條消息都只會發(fā)送給分組中的一個消費者,不同的消費者分組消費自己特定的 Topic 下面的消息,互不干擾。
8. Kafka 的擴展性
Kafka 的擴展性主要體現(xiàn)在以下幾個方面:
- 水平擴展:通過增加 Broker 節(jié)點,可以輕松擴展 Kafka 集群的存儲和處理能力。
- Partition 擴展:通過增加 Partition 數(shù)量,可以提高 Topic 的并行處理能力。
- 動態(tài)配置:Kafka 支持在運行時動態(tài)調(diào)整部分配置,如 Topic 的分區(qū)數(shù)量和副本因子等。