在曾經很長一段時間裡,ZooKeeper都是 Kafka的标配,現如今,Kafka官方已經在慢慢去除ZooKeeper,Kafka 為什麼要抛棄 Zookeeper?這篇文章我們來聊聊其中的緣由。
Kafka 和 ZooKeeper 的關系
ZooKeeper 是一個分布式協調服務,常用于管理配置、命名和同步服務。長期以來,Kafka 使用 ZooKeeper 負責管理叢集中繼資料、控制器選舉和消費者組協調等任務理,包括主題、分區資訊、ACL(通路控制清單)等。
ZooKeeper 為 Kafka 提供了選主(leader election)、叢集成員管理等核心功能,為 Kafka提供了一個可靠的分布式協調服務,使得 Kafka能夠在多個節點之間進行有效的通信和管理。然而,随着 Kafka的發展,其對 ZooKeeper的依賴逐漸顯露出一些問題,這些問題也是下面 Kafka去除 Zookeeper的原因。
抛棄ZooKeeper的原因
1. 複雜性增加
ZooKeeper 是獨立于 Kafka 的外部元件,需要單獨部署和維護,是以,使用 ZooKeeper 使得 Kafka的運維複雜度大幅提升。運維團隊必須同時管理兩個分布式系統(Kafka和 ZooKeeper),這不僅增加了管理成本,也要求運維人員具備更高的技術能力。
2. 性能瓶頸
作為一個協調服務,ZooKeeper 并非專門為高負載場景設計, 是以,随着叢集規模擴大,ZooKeeper在進行中繼資料時的性能問題日益突出。例如,當分區數量增加時,ZooKeeper需要存儲更多的資訊,這導緻了監聽延遲增加,進而影響Kafka的整體性能34。在高負載情況下,ZooKeeper可能成為系統的瓶頸,限制了Kafka的擴充能力。
3. 一緻性問題
Kafka 内部的分布式一緻性模型與 ZooKeeper 的一緻性模型有所不同。由于 ZooKeeper和 Kafka控制器之間的資料同步機制不夠高效,可能導緻狀态不一緻,特别是在處理叢集擴充或不可用情景時,這種不一緻性會影響消息傳遞的可靠性和系統穩定性。
4. 發展自己的生态
Kafka 抛棄 ZooKeeper,我個人覺得最核心的原因是:Kafka生态強大了,需要自立門戶,這樣就不會被别人卡脖子。縱觀國内外,有很多這樣鮮活的例子,當自己弱小時,會先選擇使用别家的産品,當自己羽翼豐滿時,再選擇自建完善自己的生态圈。
引入KRaft
為了剝離和去除 ZooKeeper,Kafka 引入了自己的親兒子 KRaft(Kafka Raft Metadata Mode)。KRaft 是一個新的中繼資料管理架構,基于 Raft 一緻性算法實作的一種内置中繼資料管理方式,旨在替代 ZooKeeper 的中繼資料管理功能。其優勢在于:
- 完全内置,自包含:KRaft 将所有協調服務嵌入 Kafka 自身,不再依賴外部系統,這樣大大簡化了部署和管理,因為管理者隻需關注 Kafka 叢集。
- 高效的一緻性協定:Raft 是一種簡潔且易于了解的一緻性算法,易于調試和實作。KRaft 利用 Raft 協定實作了強一緻性的中繼資料管理,優化了複制機制。
- 提高中繼資料操作的擴充性:新的架構允許更多的并發操作,并減少了因為擴充性問題導緻的瓶頸,特别是在高負載場景中。
- 降低延遲:在消除 ZooKeeper 作為中間層之後,Kafka 的延遲性能有望得到改善,特别是在涉及選主和中繼資料更新的場景中。
- 完全自主:因為是自家産品,是以産品的架構設計,代碼開發都可以自己說了算,未來架構走向完全控制在自己手上。
KRaft的設計細節
- 控制器(Controller)節點的去中心化:KRaft 模式中,控制器節點由一組 Kafka 服務程序代替,而不是一個獨立的 ZooKeeper 叢集。這些節點共同負責管理叢集的中繼資料,通過 Raft 實作資料的一緻性。
- 日志複制和恢複機制:利用 Raft 的日志複制和狀态機應用機制,KRaft 實作了對中繼資料變更的強一緻性支援,這意味着所有控制器節點都能夠就叢集狀态達成共識。
- 動态叢集管理:KRaft 允許動态地向叢集中添加或移除節點,而無需手動去 ZooKeeper 中更新配置,這使得叢集管理更為便捷。
下面給出一張 Zookeeper 和 KRaft的對比圖:
總結
本文,我們分析了為什麼 Kafka 要移除 ZooKeeper,主要原因有兩個:ZooKeeper不能滿足 Kafka的發展以及 Kafka想建立自己的生态。在面臨越來越複雜的資料流處理需求時,KRaft 模式為 Kafka 提供了一種更高效、簡潔的架構方案。不論結局如何,Kafka 和 ZooKeeper曾經也度過了一段美好的蜜月期,祝福 Kafka 在 KRaft模式越來越強大,為使用者帶來更好的體驗。