快手 EB 級 HDFS 挑戰與實踐
導讀:
作爲快手內部數據規模和機器規模最大的分佈式文件存儲系統,HDFS 一直伴隨着快手業務的飛速發展而快速成長。
本文主要從以下三個層面,介紹下 HDFS 系統在快手業務場景下的落地實踐:
-
HDFS 架構介紹
-
快手 HDFS 數據和集羣規模介紹
-
快手 HDFS 挑戰與實踐
HDFS 全名 Hadoop Distributed File System,是 Apache Hadoop 的子項目,也是業界使用最廣泛的開源分佈式文件系統。
核心思想是:將文件按照固定大小進行分片存儲,具備:強一致性、高容錯性、高吞吐性等
架構層面是典型的主從結構:
-
主節點:稱爲 NameNode,主要存放諸如目錄樹、文件分片信息、分片存放位置等元數據信息
-
從節點:稱爲 DataNode,主要用來存分片數據
HDFS 官網架構
1. 業務類型
2. 集羣規模
作爲數據平臺中最底層的存儲系統,目前也是整個快手中機器規模和數據規模最大的分佈式存儲系統,單個 HDFS 集羣擁有:
-
幾萬臺服務器
-
幾 EB 數據規模、幾百 PB 的 EC 數據量
-
每天擁有幾百 PB 的數據吞吐
-
幾十組 NameService
-
幾百億元數據信息
-
百萬級 Qps
03
快手 HDFS 挑戰與實踐
在數據爆炸式增長的過程中,HDFS 系統遇見的挑戰是非常大的。接下來,主要從 HDFS 架構四個比較核心的問題入手,重點介紹下快手的落地過程。
-
主節點擴展性問題
-
單 NS 性能瓶頸問題
-
節點問題
-
分級保障問題
1. 主節點擴展性問題
衆所周知,主節點擴展性問題是一個非常棘手,也是非常難解決的問題。當主節點壓力過大時,沒辦法通過擴容的手段來快速分擔主節點壓力。
隨着集羣規模越來越大,問題也越來越嚴重。我們認爲要解決這個問題,至少需要具備兩個能力:
-
具備快速新增 NameService 的能力
-
具備新增 NS 能快速分擔現存 NS 壓力的能力
無論社區 2.0 的 Federation 架構,還是社區最新 3.0 的 Router Based Federation 架構,都不能很好的滿足這兩個條件。綜合討論了多個方案之後,我們決定在社區最新 3.0 的 RBF 架構基礎上,進行深度定製開發,來解決主節點擴展性問題。
首先,我們介紹兩個業務場景的擴展性方案:
① 快手 FixedOrder && RbfBalancer 機制
我們支持的第一個擴展性機制:FixedOrder 機制
-
將一個路徑掛載到多個 NS 上,記爲 FixedOrderMountPoint
-
FixedOrderMountPoint 下所有新建目錄或文件都寫到期望的 NS(比如新增 NS)
-
FixedOrderMountPoint 下目錄或文件的訪問,通過探測的方式,可以有效的訪問到新老數據(增加 FixedOrderMountPoint 前後的文件或目錄)
利用這個機制,可以通過快速新增 NS,來有效緩解熱點 NS Qps 壓力過大的問題。
除此之外,我們還研發了 RbfBalancer 機制,通過 FastCp 的方式,在業務完全透明的場景下將存量數據異步搬遷到新的 NS 裏,達到緩解老 NS 內存壓力的效果。由於老 NS Qps 壓力已經被快速分擔,所以異步數據遷移的進度,沒有強要求。
利用 FixedOrder + RBFBalancer 機制,通過擴容新 NS 並快速分擔老 NS 的壓力,來解決大多數場景的擴展性問題。
② 快手 DFBH 機制
-
Qps 非常大,需要多個 NS 承擔
-
具有短暫的生命週期
針對這一類路徑 ,我們引入了 DFBH 機制,來解決主節點擴展性問題:
-
通過一致性 Hash 實現多 NS 間 Qps 負載均衡
-
利用動態 FixedOrder 機制,在不搬遷數據的場景下,實現透明擴縮容 NS
實現的核心思想是:
-
每個路徑依據多組一致性 Hash 列表計算出歸屬 NS,組合成 FixedOrder
-
將增量數據寫到期望 NS 中 ,存量數據依舊可見
-
隨着生命週期推移,逐步回退到最普通的一致性 Hash 策略
社區貢獻
除了完善多個擴展性方案之外,我們還解決了大量 RBF 正確性、性能、資源隔離等穩定性問題,同時也積極爲社區提供大量 BugFix,有興趣的同學可以參考下:
https://issues.apache.org/jira/browse/HDFS-15300
https://issues.apache.org/jira/browse/HDFS-15238
https://issues.apache.org/jira/browse/HDFS-14543
https://issues.apache.org/jira/browse/HDFS-14685
https://issues.apache.org/jira/browse/HDFS-14583
https://issues.apache.org/jira/browse/HDFS-14812
https://issues.apache.org/jira/browse/HDFS-14721
https://issues.apache.org/jira/browse/HDFS-14710
https://issues.apache.org/jira/browse/HDFS-14728
https://issues.apache.org/jira/browse/HDFS-14722
https://issues.apache.org/jira/browse/HDFS-14747
https://issues.apache.org/jira/browse/HDFS-14741
https://issues.apache.org/jira/browse/HDFS-14565
https://issues.apache.org/jira/browse/HDFS-14661
2. 單 NS 性能瓶頸問題
衆所周知,HDFS 架構中 NameNode 的實現中有一把全局鎖,很容易就達到處理瓶頸。社區最新 3.0 提出了一個 Observer Read 架構,通過讀寫分離的架構,嘗試提升單個 NameService 的處理能力,但是最新的架構問題比較多。
針對單 NS 性能瓶頸這個問題,我們嘗試從兩個階段解決:
-
快手特色 ObserverRead 架構,從讀寫分離角度提升 NS 處理能力【重點介紹】
-
優化 NameNode 全局鎖,從提升單 NN 處理能力角度提升 NS 處理能力【進行中】
快手特色 ObserverRead 架構
快手特色 ObserverRead 架構是基於最新的 RBF 框架落地的,在客戶端完全透明的場景下,實現動態負載路由讀請求的功能,提升整個 NS 處理能力。
相比社區的 ObserverRead 架構,快手特色 ObserverRead 架構有幾個非常明顯的優勢:
-
整個架構,基於 RBF 框架實現,客戶端完全透明
-
Router 檢測 NN 節點狀態,實現動態負載路由讀請求
-
Standby、Active 節點可以支持讀請求
-
Observer 節點支持快速擴容
在整個最新架構落地過程中,也解決了社區 ObserverRead 架構大量穩定性問題,比如:
-
MSync RPC 穩定性問題
-
Observer Reader 卡鎖問題
-
NameNode Bootstrap 失敗問題
-
Client Interrupt 導致無效重試問題(HDFS-13609)
3. 慢節點問題
隨着集羣規模越來越大,慢節點問題也越來越明顯,經常導致作業出現長尾 Task、訓練 “卡住” 等問題。
慢節點問題主要體現在從節點 DataNode 上,主要是因爲物理指標負載比較大,比如:網卡流量、磁盤 Util、Tcp 異常等。
針對這個問題,我們從兩個大的方向着手解決:
-
慢節點規避
-
慢節點根因優化
① 慢節點規避
主要從事先規避和事中熔斷兩個角度來實現 HDFS 層面的慢節點規避機制。
事先規避,即客戶端在讀寫數據前,NameNode 依據 DN 的負載信息進行排序,優先返回低負載的 DN。
其判斷依據主要有:負載指標(CPU 使用率、磁盤 Util、網卡流量、讀寫吞吐量);客戶端上報慢節點。
事中熔斷,即客戶端在讀寫數據過程中,通過吞吐閾值實時感知慢節點,進行實時慢節點摘除功能。
通過事先規避和事中熔斷機制,能有效地解決長尾 Task、訓練 “卡住” 等問題。
② 慢節點根因優化
從資源利用率最大化的角度出發,從節點 DataNode 機器是和 Yarn NodeManager 混布的。
通過硬件指標採集發現:Yarn MapReduce 的 shuffle 功能對硬件繁忙程度貢獻度非常大,所以我們從 Yarn Shuffle 優化和 DN 內部機制優化兩個角度嘗試從根因入手解決慢節點問題。
這裏,我主要介紹下 DN 內部優化邏輯,主要包括:
- 在線目錄層級降維
即 DN 在不停讀寫的場景下,實現 block 存儲目錄的降維工作,極大地縮減磁盤元數據信息。
- DataSet 全局鎖優化
將 DN 內部全局鎖細粒度化,拆分成 BlockPool + Volume 層級,降低 BlockPool 之間、磁盤之間的相互影響。
- Du 操作優化
將定期的 DU 操作,通過內存結構計算單磁盤 BP 使用量。
- 選盤策略優化
添加負載選盤策略,優先選擇負載比較低的磁盤。
4. 分級保障問題
衆所周知,快手經常有一些大型活動,比如春節活動、電商活動、拉新活動等,而且整個活動過程中還伴隨着無數個例行任務。
瞬間的洪峯流量,可能會導致 HDFS 系統滿載,甚至過載。
爲了在 HDFS 系統滿載的場景下儘可能的保障高優先級任務正常運行,所以我們將所有任務抽象成高優先級、中優先級和低優先級任務,同時 HDFS 系統支持分級保障功能,來滿足這個需求。
我們主要從 NameNode 和 DataNode 兩個角色入手,支持分級保障功能。
NameNode 分級保障功能
我們深度定製了 NameNode Rpc 框架,將隊列拆分成優先級隊列,Handler 依據資源配比依次處理不同優先級隊列請求。與此同時,通過壓力感知模塊,實時感知各個優先級請求的壓力,並動態調整資源配比,從而實現:
-
未滿載時,按照資源配配比處理請求
-
滿載時,資源傾向高優,優先處理高優請求
DataNode 分級保障功能
由於 DataNode 內部是通過獨佔線程方式與客戶端進行數據 IO 的,所以我們在每個磁盤上添加了磁盤限速器。
當磁盤資源達到上限後,高優先級請求到來時,會強佔低優先級資源。除此之外,我們還添加了閾值調整模塊,實時感知相關指標,動態調整磁盤限速器閾值,來控制單盤壓力。
5. 快手 HDFS 架構圖
最後,我們介紹下目前快手 HDFS 系統的最新架構。
整個架構整體分爲三層,分別是:路由層、元信息層和數據層。
① 路由層
由一組無狀態的 Router 服務組成,Router 間通過 ZK 來共享掛載點信息等,主要用於轉發客戶端的元信息請求。
② 元信息層
由多組相互獨立的 NameService 組成,每組 NameService 內主要有一臺 Active NameNode 服務、一臺 Standby NameNode 服務、N 臺 Observer NameNode 服務組成。
其中:
-
Active 和 Standby 通過 ZKFC 實現動態 HA 切換的功能
-
Active 主要承擔寫請求壓力
-
Standby 除了承擔定期 Checkpoint 功能外,還支持部分讀請求
-
Observer 主要分擔讀請求壓力
③ 數據層
由一組無狀態的從節點 (DataNode) 組成,主要用來存在數據;通過心跳、塊彙報等 Rpc 與主節點保持最新狀態。
04
結尾
快手 HDFS 經歷了 3 年的發展,從最初的幾百臺節點支持 PB 級數據量的小規模集羣,到現在的擁有幾萬臺節點支持 EB 級數據量的超大規模集羣。我們團隊用無數個黑夜,經歷了數據爆炸式增長的過程,抗住了巨大壓力,踩了無數的坑,同時也積累大量經驗。
當然,快手依舊處於飛速發展過程中,我們團隊依舊不忘初心,懷着敬畏之心,繼續匠心前行。
今天的分享就到這裏,謝謝大家。
分享嘉賓:
徐增強,快手分佈式存儲高級研發工程師。主要負責 HDFS 系統 的運維和研發工作,Hadoop、Kafka 活躍 Contributor,主要關注分佈式存儲技術領域。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/_cpPGlVjqHoc9wcbbvigMA