位元組跳動10萬節點 HDFS 叢集多機房架構演進之路

語言: CN / TW / HK

背景

現狀

HDFS 全稱是 Hadoop Distributed File System,其本身是 Apache Hadoop 專案的一個模組,作為大資料儲存的基石提供高吞吐的海量資料儲存能力。自從 2006 年 4 月份釋出以來,HDFS 目前依然有著非常廣泛的應用,以位元組跳動為例,隨著公司業務的高速發展,目前 HDFS 服務的規模已經到達“雙 10”的級別:

  • 單叢集節點 10 萬臺級別

  • 單叢集資料量達到 10 EB 級別

主要使用場景包括

  • 離線

    • OLAP 查詢引擎儲存底座,包括 Hive/ClickHouse/Presto 等場景

    • 機器學習離線訓練資料

  • 近線

    • ByteMQ

    • 流式任務 Checkpoint

業界很多公司在維護 HDFS 服務時,採用的都是小叢集模式,即生產上部署多個隔離獨立的 HDFS 叢集滿足業務的不同需求。位元組跳動採用的是橫跨多個機房的聯邦大叢集部署模式,即 HDFS 只有一個叢集,這個叢集有多個 NameService,但是底層的 DN 是橫跨 A/B/C 3 個機房的 ,由於社群版 HDFS 沒有機房感知相關的支援,因此位元組跳動 HDFS 團隊在這個功能上做了專門的設計和實現,本文會介紹這部分的工作。

動機

業務的迅猛發展和業務場景的多樣性給 HDFS 帶來了很大的挑戰,這裡列幾個比較有代表性的問題

  • 如何在容量上滿足業務的發展需求

  • 如何滿足近線場景對低延遲的需求

  • 如何滿足關鍵業務的機房級別容災需求

  • 如何高效運維如此超大規模的叢集

要回答這些問題需要 HDFS 從多個方向迭代優化,例如 DanceNN 的上線、運維平臺的建設等,本文將會聚焦在 HDFS 多機房架構的演進策略上,它直接回答了上面提到的兩個問題,即:

  • 如何在容量上滿足業務的發展需求:資料如何合理地在多個機房之間存放以便能通過其他機房的資源進行快速擴容?

  • 如何滿足關鍵業務的容災需求:系統如何滿足核心業務機房級別的容災需求?

社群版架構

位元組跳動的 HDFS 技術脫胎於社群版 HDFS,為了方便大家理解內部版本的技術發展歷程,本小節我們將先了解一下社群 HDFS 的架構。

圖(1)  社群版 HDFS 架構

從圖(1) 可以看出,社群 HDFS 從架構上劃分可以分為 3 部分:

  • Client:訪問 HDFS 的 client,主要通過 HDFS SDK 和 HDFS 進行互動,HDFS SDK 的實現比較重,很多 IO 處理邏輯都是在 SDK 實現,因此這裡單獨列為架構的一部分。

  • 元資料管理:即 NameNode,負責叢集的元資料管理,包括目錄樹和資料塊的位置資訊。為了解決元資料膨脹問題,社群提供了 Federation 的功能,引入了 NameService 的概念,簡單地說,每一個 NameService 提供一個 NameSpace,為了保證 NameNode 的高可用,一個 NameService 包含多個 NameNode 節點(一般是 2 個),這些 NameNode 節點以一主多備的模式工作。Federation 功能跟多機房架構並沒有必要的關聯,因此接下來討論我們將不會涉及 Federation/NameService 等概念。

  • 資料管理:即 DataNode,負責存放使用者的實際資料,前面提到 NameNode 一個功能是管理資料塊的位置資訊,在具體實現上,NameNode 不會持久化這些塊的資訊,而是靠 DataNode 主動彙報來維護。

到目前為止,HDFS 叢集的多機房架構相關的方案基本都是元資料層完成的,因此接下來我們的討論將會聚焦在元資料部分。在本文剩餘篇幅裡,除非特別宣告,否則相關術語都是指位元組跳動版的 HDFS。

位元組版架構

圖(2)  位元組跳動 HDFS 架構

注:由於 BookKeeper 自身的架構設計,NameNode(DanceNN) 實際上是需要通過 ZooKeeper 去發現 BookKeeper 的 EndPoint 資訊的,這裡為了方便理解,沒有把這部分通訊關係畫出來。

對比圖(1) 和 圖(2), 我們可以發現,位元組跳動的 HDFS 依然保留了社群 HDFS 的核心架構,同時也加入了一些特有的功能,包括:

  • DanceNN,即位元組跳動用 C++ 重新實現的 NameNode,協議上基本相容社群版的 NameNode。除非特別說明,否則後面出現 DanceNN、NameNode 均指代 DanceNN。

  • NNProxy,即 NameNode Proxy,為 Federation 功能提供統一的 Namespace,由於跟多機房架構直接關係不大,這裡不再詳細展開。

  • BookKeeper, 即 Apache BookKeeper,其作用是跟社群的 JournaNode 是一樣的,就是為 Active 和 Standby NameNode 提供一個共享的 EditLog 儲存方案,這是實現 NameNode 的 HA 方法的基礎。

值得一提的是,BookKeeper 本身提供了機房級別的儲存配置策略,這是 HDFS 多機房容災方案的基礎,這個特性確保了 HDFS NameNode 提供跨機房容災能力,後面我們將繼續深入討論。

 

演進

雙機房

前面提到當前 HDFS 的大叢集是橫跨 A/B/C 的多機房模式,具體的演進順序是 A -> A,B -> A,B,C ,現在也保持了直接擴充套件到更多機房的能力。本小節將著重介紹 A -> A,B 的雙機房演進過程,後面的多機房架構的設計思想主要還是雙機房架構的擴充套件。

資料放置

圖(3) 位元組跳動 HDFS 雙機房 DataNode 結構

HDFS 雙機房資料放置方案在設計上總結起來可以描述如下:

  • A/B 機房的 DN 直接跨機房組成一個雙機房叢集,向相同的 NameNode 彙報。

  • 每一個檔案在寫的時候會保證每個機房至少存在一個副本,資料實時寫到兩個機房。

  • 每個 Client 在讀取檔案的時候,優先讀取本機房的副本,避免產生大量的跨機房讀頻寬。

這個設計的好處就是儲存層對上層應用遮蔽了叢集細節,計算資源可以直接無感分配。該設計結合離線資料一寫多讀的特點,充分考慮跨機房頻寬的合理使用。

  • 由於寫頻寬一般不會有突發,機房間的離線頻寬可以支撐同步寫的需求,因此資料可以兩個機房同步放置至少一個副本。

  • 離線查詢容易有大的突發請求,因此需要確保常規狀態下沒有突發的跨機房讀頻寬。

在實現上關鍵是 DanceNN 加入了機房的感知能力,DanceNN 在 Client 進行資料操作時加入對機房拓撲的識別,由於 DanceNN 對外的協議沒有改動,因此上層應用不需要做感知改動。

容災設計

前面介紹了雙機房架構裡資料放置的設計,它解決了容量擴充套件的問題,但是並沒有解決機房級別的容災問題,儘管 NameNode 以一主多備的形式實現了高可用,但是所有 NameNode 還是放在一個機房,在位元組跳動基礎架構的容災體系裡,是需要做到機房級別的容災。

由於 HDFS 的資料已經實現了多機房資料副本的同步寫入,為了達成容災的目標,只需要把元資料也演進到雙機房架構即可實現機房級別的容災。

前面我們所說的 HDFS 的元資料元件其實包含了兩部分,即 NameNode 和 NameNode Proxy(NNProxy),由於 NNProxy 是無狀態的轉發服務,因此元資料的多機房架構我們只需要關注在 NameNode 設計上。

圖(4) 位元組跳動 HDFS NameNode 體系

從圖(4) 可以看出NameNode 包含了 3 個關鍵模組:

  • Apache ZooKeeper,為 Apache BookKeeper 提供元資料服務。

  • Apache BookKeeper,為 NameNode 的高可用方案提供 EditLog 共享儲存方案。

  • DanceNN,即位元組跳動自研的高效能 NameNode 實現。

這 3 者構成一個分層的單向依賴關係鏈, DanceNN -> BookKeeper -> ZooKeeper,因此這 3 者可以獨立完成雙機房的容災方案,最終在整體上呈現一個雙機房容災的 NameNode 元資料服務。

元件 多機房方案
Zookeeper 一個 ZK Ensemble 由 5 臺 Server 組成,這 5 臺 Server 分佈在 3 個機房,分佈比例為 A:B:C = 2:2:1
BookKeeper 一個 BK cluster 通常由 14 臺 Server 組成,分佈在 2 個機房,分佈比例為 1:1
DanceNN 一個 NameService 包含 5 個 DanceNN,這個 5 個 DanceNN 分佈在 2 個機房,分佈比例為 3:2,工作模式為 1 Active + 4 Standby

在實現上,這裡面的關鍵就是DanceNN 的 EditLog 機房寫策略,因為 DanceNN 在做主備切換的時候,如果EditLog沒法保持同步,那麼服務是不可用的,得益於 BookKeeper 的機房感知的資料放置功能,DanceNN 可以通過這些策略來完成雙機房容災方案。

  • 常態下,EditLog會以 4 個副本存放到 BookKeeper 上,這 4 個副本的機房分佈比例為 1:1。

  • 容災場景下,DanceNN 可以快速切換成單機房模式,EditLog依然以 4 個副本存放,但是儲存策略變為單機房儲存,歷史的EditLog也能正常消費。

旁路系統

前面已經介紹完了 HDFS 雙機房方案的主體設計,但是事實上一個方案的推進落地除了架構上的迭代演進之外,還需要一系列的旁路系統來配合支援,包括:

  • Balancer:需要感知機房放置

  • Mover:需要保證資料的實際放置滿足多機房策略

  • 運維繫統

    • 在 Federation 架構下,多個 NameService 需要保證切主的效率

    • 運維操作預案:提前預判相關可能的故障,並且能在運維繫統上執行

  • 業務的平穩過渡方案,儘可能少地減少對業務干擾

限於篇幅,本文不再進行細節展開。

多機房

HDFS 多機房架構是對雙機房架構的擴充套件,其研發直接動機是機房的資源供應短缺問題,例如 2020 年 B 機房幾乎就沒有資源供應,但是在公司新的主機房 C 卻有較為充裕的資源。

一開始我們是嘗試將 C 機房作為一個獨立的叢集提供服務,但是發現業務的血緣關係太過複雜,遷移成本太高,因此選擇了基於雙機房機房擴充套件到多機房的方法,該方案需要滿足這些需求:

  • 合理使用跨機房頻寬

  • 相容已有的雙機房方案

  • 遷移成本儘可能小

  • 符合位元組跳動的機房級別容災標準

最終的設計方案為:

  • 資料放置策略支援多機房,同時相容已有的雙機房放置策略

  • NameNode 的容災方案策略不變,因為在多機房架構下,HDFS 依然只保證一個機房範圍的故障容災

相應的旁路系統也做相應的調整,儘管 HDFS 底層提供了資料放置在多個機房的策略,但是在離線場景中,使用者只能選擇 2 個機房存放,例如 A/B, B/C,A/B,這個運營上的策略選擇是綜合考慮了穩定性、頻寬使用的合理性以及資源的合理利用之後確定的,核心目標還是保障業務的平穩發展,從後續實踐下來看,這個策略是一個非常正確的選擇。

 

總結

根據我們的不完全調研,位元組跳動 HDFS 的多機房架構在業界中是較為特別的,箇中原因主要還是公司業務的高速發展和機房建設方向的獨特性,這些因素驅動我們進行獨特的迭代演進,從結果來看是達到了預期的,例如 2020 年 C 機房的充分使用,在 B 機房沒有資源供應的情況下依然保障了業務的平穩;2021 春晚活動,為近線業務例如 BMQ、流式 CheckPoint 等提供了多機房的容災策略保障。

最後,HDFS 的多機房架構依然在持續迭代,中長期來看,不排除有更多新機房出現的可能,這些都給 HDFS 多機房架構提出了更多的挑戰,當原本的多機房方案的基礎條件不再具備時,HDFS 團隊也會開啟相關功能的迭代。

邀測!火山引擎大資料檔案儲存

位元組跳動大資料儲存團隊將在技術上的探索和業務上的積累結合,打造出了檔案儲存產品“大資料檔案儲存”,目前火山引擎大資料檔案儲存正式開始邀測。

大資料檔案儲存支援完整的 HDFS 語義,無需修改原生代碼即可使用的高可靠,低成本,無限容量的分散式檔案系統。與火山引擎 VKE/VCI 相結合可提供快取加速,多級資料快取,多模式支援等能力。採用雲中立模式,支援公有云、混合雲及多雲部署,全面貼合企業上雲策略。

 

位元組跳動大資料儲存團隊負責整個位元組跳動全球大資料儲存基礎設施的建設,支援今日頭條、抖音、電商、遊戲等眾多產品線,長期致力於超大規模儲存系統的技術演進,歡迎更多同學加入我們,一起構建下一代 10 EB 級別的儲存系統。