萬億級Kafka訊息規模下的降本增效之旅

作者 | 京東研發工程師 鍾厚
JDQ 平臺介紹
京東內部使用基於 Apache Kafka 構建的 JDQ 來支援其平臺業務。JDQ 是京東集團大資料平臺統一的即時資料匯流排,賦能集團內部京東零售、物流、科技、健康、安聯等 40 多個一級部門,搜尋推薦、廣告、點選流、即時大屏等 1400+ 的業務線。JDQ  當前叢集規模多達 6000 多個節點,每天產生的記錄數達 15 萬億,峰值出頻寬達到 1TB/s
JDQ 平臺採用 Kubernetes 進行有狀態服務編排,透過 StatefulSet 控制器管理整個叢集,支援多種儲存方案和服務訪問方式。該平臺可部署在私有云、公有云以及京東內部的 Kubernetes 平臺上。隨著公司整體技術架構向基於 Kubernetes 的雲原生架構演進,JDQ 在 Kubernetes 上的執行效率、成本和彈性都面臨新的挑戰。
JDQ Architecture
CubeFS 介紹
CubeFS(原名 ChubaoFS)是一款新一代雲原生開源儲存系統,是雲原生計算基金會(CNCF)的畢業專案。該開源專案由社群和 OPPO 等多家公司共同維護和發展,持續在雲端儲存、高效能計算等領域最佳化演進。京東作為該專案的早期發起者,在內部大規模應用,支撐了海量離線上業務的穩定執行。
CubeFS 支援 S3、HDFS 和 POSIX 等訪問協議,廣泛適用於大資料、AI/LLMs、容器平臺、資料庫和中介軟體等場景,提供儲存與計算分離、資料共享和分發等能力。
CubeFS 由 元資料子系統(Metadata Subsystem) ,資料子系統(Data Subsystem) 和 資源管理節點(Master) 以及 物件閘道器(Object Subsystem) 組成,可以透過 POSIX/HDFS/S3 介面訪問儲存資料。
CubeFS Architecture
京東大規模應用
Kafka 時帶來的挑戰
儲存、網路頻寬浪費導致成本上升
京東 JDQ 底層儲存採用支援 S3 協議的 CubeFS 物件儲存。CubeFS 透過多副本機制來保證資料永續性,而 Kafka 則使用 ISR 多副本機制實現相同目的。Apache Kafka 誕生於十幾年前,其架構專為 IDC 物理機部署而設計。Kafka 將資料儲存在本地磁碟上,並透過多副本的 ISR 機制來確保資料永續性。這種設計在當時是合理的。然而,隨著雲計算時代的到來,基於 S3 等物件儲存的共享儲存架構逐漸興起,Kafka 的傳統架構顯得不夠最佳化。以京東為例,當 Kafka 直接部署在 CubeFS 上時會產生大量資料冗餘:針對 Kafka 的一份寫入資料,由於 ISR 需要進行副本複製,真正儲存到 CubeFS 上以後,考慮到 CubeFS 內部的多副本機制,實際儲存了 9 份資料,其中約 66.67%(6/9)的儲存空間被不必要的資料冗餘佔用,造成了嚴重的資源浪費。
此外,Kafka 層面的副本複製以及寫遠端 CubeFS 還會消耗額外的網路頻寬。這導致在當前架構下,Kafka 的 ISR 機制反而造成了儲存和網路頻寬資源的過度使用,最終增加了總體成本。下圖展示了 Kafka 部署在 CubeFS 上時,冗餘資料是如何產生的。其中虛線的資料塊則是冗餘的資料副本。
Waste of Storage and Network Bandiwith of Kafka
Apache Kafka 架構不是 Kubernetes 雲原生
Kubernetes 為企業帶來了諸多益處,尤其是透過容器化和 Pod 抽象顯著提升了硬體資源利用率,並降低了成本。在全面 Kubernetes 化的背景下,像 Apache Kafka 這樣的核心基礎軟體也需要部署在 Kubernetes 上,以充分利用其資源最佳化優勢。京東內部已將 50% 的物理節點上的 Kafka 叢集遷移至 Kubernetes,在這個過程中我們深切體會到了 Kafka 本身架構在 Kubernetes 上執行所帶來的挑戰。Apache Kafka 採用存算一體的 Shared-Nothing 架構,其計算節點 Broker 與本地儲存緊密耦合,這使得其難以在 Kubernetes 上實現靈活的擴縮容。
以擴容為例,Apache Kafka 擴容時必須經歷如下幾個過程:
  • 仔細制定分割槽遷移策略,確保各個 Broker 之間的整體流量保持均衡
  • 評估遷移影響,制定預案,提前通知 Kafka 上下游應用
  • 在業務低峰期執行擴容操作,進行分割槽資料遷移(根據資料量大小,可能耗時數分鐘到數小時)
  • 分割槽遷移完畢後,檢測叢集狀態,確保流量在 Broker 之間保持均衡
由於 Kafka 的架構不符合 Kubernetes 原生設計理念,其擴縮容操作在 Kubernetes 上成為了一個需要人工介入的高風險操作。在這種限制下,Apache Kafka 只能作為與 Pod 繫結的靜態資源部署。Kubernetes 無法根據叢集資源利用率來自動擴縮容節點和排程 Pod,因此也就無法發揮其優勢。
Kafka Scaling on Kubernetes
AutoMQ 如何解決京東 Kafka 挑戰
在尋求解決京東內部 Kafka 挑戰的調研過程中,我們發現了 AutoMQ[1] 這一優秀產品。AutoMQ 採用計算與儲存分離的共享儲存架構,在確保與 Apache Kafka 完全相容的同時,可將資料儲存到相容 S3 協議的物件儲存之上,從而顯著降低成本並提升效率。
具體而言,AutoMQ 透過技術創新解決了京東內部 JDQ 雲原生化過程中的主要挑戰:
S3 API 協議相容適配 CubeFS:AutoMQ 相容標準的 S3 API 協議,不僅可適配標準雲物件儲存服務,還支援 MinIO、Ceph 以及 CubeFS 等相容 S3 API 的物件儲存介質。這使得 AutoMQ 能夠與京東內部的 CubeFS 服務自然整合。
100% 完全相容 Kafka,利於遷移:鑑於京東內部擁有大規模的 Kafka 叢集及其周邊基礎設施,AutoMQ 的完全相容性確保了現有業務無需任何程式碼改造和配置修改即可無縫遷移,同時可充分利用現有 Kafka 生態系統。
資料解除安裝至雲端儲存,顯著降低儲存、頻寬資源:AutoMQ 基於 WAL 和物件儲存構建的共享儲存架構實現了計算與儲存的完全分離。不同於 Apache Kafka 的 ISR 多副本機制,AutoMQ 將資料永續性直接委託給 S3/CubeFS 等物件儲存服務。這種設計使得寫入 Broker 的資料在 CubeFS 層面僅產生 3 份副本,大幅降低了儲存資源消耗。由於採用單一 Leader Partition 設計,AutoMQ 還節省了傳統 Kafka Replica 寫入遠端 CubeFS 產生的網路頻寬開銷。
Offload Kafka Data Durability to Object Storage
極速彈性、自動平衡:AutoMQ 架構無需像 Kafka 那樣遷移分割槽資料就能完成擴縮容。遷移分割槽只需更新元資料,在 1 秒左右即可完成。AutoMQ 內建的 Self-Balancing 元件持續監控叢集狀態,即時進行業務無感知的分割槽遷移和排程,確保叢集流量和 QPS 始終保持均衡。憑藉這種彈性優勢,AutoMQ 能與 Kubernetes 平臺的 Autoscaler、Karpenter 等工具完美配合,根據負載自動進行叢集擴縮容,充分發揮 Kubernetes 的潛力。
Partition Reassignment in Seconds
AutoMQ 基於 CubeFS
在京東的最佳化實踐
  • CubeFS Object Node 服務部署:CubeFS 支援 S3 協議的請求訪問,在架構實現層面是透過提供了 Object Node 對外服務,S3 協議的客戶端將請求傳送給 Object Node 服務,並從 Object Node 服務獲取到相關相應,整個請求響應的過程 S3 SDK 並不與 CubeFS 後端的 Meta Node 和 Data Node 通訊。京東 CubeFS 的 Object Node 服務對外統一透過 Load Balance 提供域名訪問,如果京東 Kafka 所有的流量請求都經過 Load Balance 進行負載均衡,則 Load Balance 服務經過估算需要上千臺機器才能支撐訪問,這種成本開銷是無法接受的。後面京東經過方案驗證與最佳化,將 Object Node 服務與 AutoMQ 服務部署在同一個 Pod 中,Object Node 和 AutoMQ 在 Pod 中處於同一個網路 namespace,可以直接給 AutoMQ 提供 Localhost 的訪問能力,從而直接繞過了 Load Balance 服務並節省了相應的成本開銷。
The optimization of ObjectNode deployment
  • CubeFS 單目錄下檔案數過多最佳化:CubeFS 同時相容 S3 和 Posix 協議訪問,使用 AutoMQ 透過 S3 協議往 CubeFS 寫入大量資料後,單個目錄下可能會產生大量的子目錄和檔案,而這些大量的子目錄為了相容 Posix 協議訪問,會對 CubeFS 後端叢集的元資料管理造成較大壓力;並且 AutoMQ 在執行 compaction 時使用 KEEP_DATA 策略,從 kraft 中刪除 metadata,但是底層 object 檔案依然存在,這些檔案會使得 CubeFS 單目錄下存在過多的子目錄;京東最佳化調整了 AutoMQ 的 MINOR_V1 引數後,將 compaction 操作透過物理合併,能將儲存在 CubeFS 的 object 檔案數量降低 90%,從而降低 CubeFS 後端叢集的元資料管理壓力。
  • CubeFS 空目錄最佳化:CubeFS 在建立物件檔案時,會將檔案字首轉換成目錄,AutoMQ 在建立資料主存物件檔案時,也會在 CubeFS 叢集上建立物件檔案的字首目錄,而物件檔案刪除後,相應的字首目錄存在沒有刪除的情況,這樣造成了 CubeFS 上面存在大量未清理的空目錄;在透過最佳化 Object Node 對字首目錄的元資料標記後,能級聯刪除物件檔案相應的字首目錄,從而消除了 AutoMQ 基於 CubeFS 產生的空目錄問題。
  • CubeFS S3 請求介面相容擴充套件:CubeFS 目前相容 S3 協議的讀寫請求訪問,但是也有個別 S3 SDK 的介面目前還沒有相容支援,比如 AutoMQ multipart object 在超過 32MB 之後呼叫的 S3 UploadPartCopy 介面,目前還沒有相容支援,後續京東規劃會根據業務場景的需求進行相容支援。
AutoMQ 在京東生產應用的效果
當前,京東採用的是 AutoMQ  S3 WAL [2] 的模式。AutoMQ 的架構設計中對於 WAL 進行了高度的抽象,可以將不同的儲存介質作為 WAL。在京東的場景中,我們將 CubeFS 本身作為了 WAL,不再依賴本地儲存,整體的架構變得十分的簡潔、高效。
AutoMQ Deployment on Kubernetes in JD.com
下圖展示了京東內部一個 AutoMQ 生產叢集的核心指標。這個叢集在採用 AutoMQ 新架構後,取得了以下成效:
叢集儲存成本降低 50%,頻寬成本降低 33%:得益於 AutoMQ 的雲原生架構,顯著降低了 Kafka 叢集在儲存和網路頻寬方面的資源需求,大幅節省了成本。
叢集在 Kubernetes 上擴容效率由小時級別提升到分鐘級別:使用 AutoMQ 後,部署在 Kubernetes 上的 Kafka 擴縮容不需要大量的複製遷移資料,將擴縮容的時效提升到了分鐘級別。AutoMQ 叢集能夠快速動態調整容量,從容應對大促、秒殺等電商場景,不僅減輕了運維負擔,還避免了為應對峰值而過度配置資源的浪費。
未來展望
AutoMQ 作為一款以“雲優先”理念設計的新一代 Kafka 與京東業務全面上雲、雲原生化的步調一致。在未來,我們將在保證叢集穩定、高可用的前提下,進一步推廣和深化 AutoMQ 在京東的應用,促進資料基礎設施全面雲化、雲原生化並且進一步降低資料基礎設施的成本、提升效率。
參考資料
[1] AutoMQ: https://www.automq.com/
[2] AutoMQ WAL Storage: https://docs.automq.com/automq/architecture/s3stream-shared-streaming-storage/wal-storage
今日好文推薦
騰訊元寶連夜修改使用者協議!“霸王”條款衝上熱榜,你的內容到底誰說了算?
“抄襲”程式碼,到底是 CTO 的鍋還是創始人的鍋?!這事兒已經撕3天了
分散式系統程式設計已停滯?!
Curl 之父:我是如何枕著18萬行C程式碼還能安穩入睡的

相關文章