Kafka 之集羣架構原理

原理至關重要,面試的時候不可能問你命令的,都是問原理,懂了原理線上如果使用 kafka 出了問題纔可能快速定位,而不是一臉蒙圈。必須要明白原理,如果不說原理直接實戰,就真成搬磚了。

Topic

創建一個 TopicA 的主題,3 個分區分別存儲在不同的服務器,注意 Topic 是一個邏輯上的概念。

Partition & Partition 副本

Kafka 的 topic 可以劃分成一個或多個 partition,Partition 是物理上的概念。如果一個 topic 的副本數設爲 3,那麼每個 partition 對應還會有 3 個相同的副本。下圖我們對 TopicA 的分區 0,1,2 分別設置了 3 個副本,再分別存儲在 broker0,1,2。

日誌分段存儲

由於生產者生產的消息會不斷追加到 log 文件末尾,爲防止 log 文件過大導致數據定位效率低下,Kafka 採取了分片和索引機制。

它將每個 Partition 分爲多個 Segment,每個 Segment 對應兩個文件:“.index” 索引文件和 “.log” 數據文件。

Leader & Follow

而且每個副本都是有角色之分的,它們會選舉一個副本作爲 leader,其餘的爲 follower。生產者在發送數據的時候,是直接發送到 leader partition,然後 follower partition 自行去 leader 進行數據同步,消費者消費數據的時候,也是從 leader 中消費數據。(下圖在 TopicA-partition-0 在 broker0 是 leader,同理其他 TopicA-partition-N 也有 leader)

Consumer & Consumer group

一個消費組由一個或多個消費者實例組成,便於擴容與容錯。一個分區不會讓同一個消費者組裏面的多個消費者去消費,一個消費者是可以去消費多個分區的數據的。

Kafka 的網絡設計

  1. 客戶端將請求發送給 Acceptor,broker 裏有 3 個 processor 的線程(默認是 3),Acceptor 不會對客戶端的請求做任何的處理,而是封裝成 socketChannel,然後發送給 3 個 processor 線程,形成一個隊列。發送的方式是輪詢,就是發送給第一個 processor,然後是第二個,第三個...

  2. 消費者線程會以 request 請求去消費這些 socketChannel;

  3. 線程池裏面默認有 8 個 ReaderThreadPool 線程,這些線程是用來處理 request 的,解析請求,返回響應結果 response;

  4. processor 會從 response 中讀取響應數據,然後再返回給客戶端。

所以如果我們需要對 kafka 進行增強調優,增加 processor 並增加線程池裏面的處理線程,就可以達到效果。request 和 response 那一塊部分其實就是起到了一個緩存的效果,是考慮到 processor 們生成請求太快,線程數不夠不能及時處理的問題。所以這就是一個加強版的 reactor 網絡線程模型。

Kafka 零拷貝

傳統 IO:

//讀取文件,再用socket發送出去buffer = File.read 
Socket.send(buffer)

1、第一次:將磁盤文件,讀取到操作系統內核緩衝區;2、第二次:將內核緩衝區的數據,copy 到 application 應用程序的 buffer;3、第三步:將 application 應用程序 buffer 中的數據,copy 到 socket 網絡發送緩衝區 (屬於操作系統內核的緩衝區);4、第四次:將 socket buffer 的數據,copy 到網卡,由網卡進行網絡傳輸。

傳統方式,讀取磁盤文件並進行網絡發送,經過的四次數據 copy 是非常繁瑣的。實際 IO 讀寫,需要進行 IO 中斷,需要 CPU 響應中斷 (帶來上下文切換),儘管後來引入 DMA 來接管 CPU 的中斷請求,但四次 copy 是存在“不必要的拷貝” 的。

零拷貝:

Kafka 使用的 zero-copy 的應用程序要求內核直接將數據從磁盤文件拷貝到套接字,而無需通過應用程序。零拷貝不僅大大地提高了應用程序的性能,而且還減少了內核與用戶模式間的上下文切換。

zookeeper 在 kafka 集羣中的作用

1、Broker 註冊

Broker 是分佈式部署並且相互獨立,但是需要有一個註冊系統能夠將整個集羣中的 Broker 管理起來,此時就使用到了 Zookeeper。在 Zookeeper 上會有一個專門用來進行 Broker 服務器列表記錄的節點:/brokers/ids

每個 Broker 在啓動時,都會到 Zookeeper 上進行註冊,即到 / brokers/ids 下創建屬於自己的節點,如 / brokers/ids/[0...N]。

Kafka 使用了全局唯一的數字 ID 來指代每個 Broker 服務器,創建完節點後,每個 Broker 就會將自己的 IP 地址和端口信息記錄到該節點中去。其中,Broker 創建的節點類型是臨時節點,一旦 Broker 宕機,則對應的臨時節點也會被自動刪除。

2、Topic 註冊

在 Kafka 中,Topic 的消息分區與 Broker 的對應關係也都是由 Zookeeper 在維護,由專門的節點來記錄,如:/borkers/topics

Kafka 中每個 Topic 都會以 / brokers/topics/[topic] 的形式被記錄,如 /brokers/topics/login 和 /brokers/topics/search 等。Broker 服務器啓動後,會到對應 Topic 節點(/brokers/topics)上註冊自己的 Broker ID,並寫入該 Topic 的分區總數,如 / brokers/topics/login/3->2,這表示 Broker ID 爲 3 的節點對 "login" 這個 Topic 提供了 2 個分區進行消息存儲。同樣,這個分區節點也是臨時節點。

3、消費者註冊

①、註冊節點到消費者分組。每個消費者服務器啓動時,都會到 Zookeeper 的指定節點下創建一個屬於自己的消費者節點,例如 / consumers/[group_id]/ids/[consumer_id],完成節點的創建後,消費者就會將自己訂閱的 Topic 信息寫入該臨時節點。

②、對消費者分組中的消費者的變化註冊監聽。每個 消費者都需要關注所屬消費者分組 其他消費者服務器的變化情況,即對 / consumers/[group_id]/ids 節點註冊子節點變化的 Watcher 監聽,一旦發現消費者新增或減少,就觸發消費者的負載均衡。

4、分區 與 消費者 的關係

在 Kafka 中,規定了每個消息分區只能被同組的一個消費者進行消費,因此,需要在 Zookeeper 上記錄 消息分區 與 Consumer 之間的關係,每個消費者一旦確定了對一個消息分區的消費權力,需要將其 Consumer ID 寫入到 Zookeeper 對應消息分區的臨時節點上,例如:

/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]

其中,[broker_id-partition_id] 就是一個 消息分區 的標識,節點內容就是該 消息分區 上 消費者的 Consumer ID。

5、消息消費進度 Offset 記錄

在消費者對指定消息分區進行消費中,需要定時地將分區消息的消費進度 Offset 記錄到 Zookeeper 上,以便在該消費者進行重啓或者其他消費者重新接管該消息分區的消息消費後,能夠從之前的進度開始繼續進行消息消費。Offset 在 Zookeeper 中由一個專門節點進行記錄,其節點路徑爲:

/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]

節點內容就是 Offset 的值。

6、生產者負載均衡

由於同一個 Topic 消息會被分區,並被分佈在多個 Broker 上,因此,生產者需要將消息合理地發送到這些分佈式的 Broker 上,那麼如何實現生產者的負載均衡,Kafka 支持傳統的四層負載均衡,也支持 Zookeeper 方式實現負載均衡。

        (1) 四層負載均衡,通常,一個生產者只會對應單個 Broker,然後該生產者產生的消息都發往該 Broker。這種方式邏輯簡單,每個生產者不需要同其他系統建立額外的 TCP 連接,只需要和 Broker 維護單個 TCP 連接即可。但是,其無法做到真正的負載均衡,因爲實際系統中的每個生產者產生的消息量及每個 Broker 的消息存儲量都是不一樣的,如果有些生產者產生的消息遠多於其他生產者的話,那麼會導致不同的 Broker 接收到的消息總數差異巨大,同時,生產者也無法實時感知到 Broker 的新增和刪除。

        (2) 使用 Zookeeper 進行負載均衡,由於每個 Broker 啓動時,都會完成 Broker 註冊過程,生產者會通過該節點的變化來動態地感知到 Broker 服務器列表的變更,這樣就可以實現動態的負載均衡機制。

7、消費者負載均衡

與生產者類似,Kafka 中的消費者同樣需要進行負載均衡來實現多個消費者合理地從對應的 Broker 服務器上接收消息。

作者:Natasha_

來源:juejin.cn/post/6890399203562881038

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