HDFS NameNode 設計實現解析

HDFS NameNode 設計實現解析

接前文 分佈式存儲-HDFS 架構解析,我們總體分析了 HDFS 架構的主要構成組件包括:NameNode、DataNode 和 Client。本文首先進一步解析 HDFS NameNode 的設計和實現要點。

元數據持久化

NameNode 將所有元信息以特定的數據結構組織存放在內存中,對於 namespace 和 replication factor 的信息會進行持久化,而映射關係則不會持久化。因爲映射關係是通過 DataNode 啓動後定時彙報上來,即使 NameNode 重啓後內存信息丟失也可以通過 DataNode 重新彙報獲得,而其他元信息則必須通過讀取持久化存儲來重建內存數據結構。出於性能原因,所有元信息的讀取直接從內存中獲得,而增刪改操作則借鑑來數據庫的事務日誌技術。每次只變更內存數據結構並記錄操作日誌,將隨機寫變爲順序寫來提高吞吐能力。

NameNode 使用一個事務日誌文件 EditLog 來持久化記錄針對文件系統元數據的每一次操作變更。而整個 file system namesapce 文件、文件塊和數據節點的映射關係被存儲在另一個 FsImage 文件中。當 NameNode 啓動時,它讀取 FsImage 文件構建元數據的內存數據結構,接着讀取 EditLog 文件應用所有的操作事務到內存數據結構中。接着基於最新的內存數據結構重新寫一個新的 FsImage 文件到磁盤上,然後清除 EditLog 的內容,因爲它上面記錄的所有操作日誌都已經反應到 FsImage 上了。這個過程稱爲建立了一個檢查點(checkpoint),當然檢查點技術也是數據庫裏最常用的了。啓動過程中 NameNode 會進入一種特殊狀態,稱爲安全模式(Safemode state),它等待 DataNode 報告文件塊及其副本的數量並確定哪些文件的副本數量是不足的。

所有上述啓動過程完成後,NameNode 才能對外提供服務。

數據分佈策略

除了文件系統元數據管理外,NameNode 另一個重要作用是對寫入的文件塊選擇合適 DataNode 來存放,稱爲 block placement policy。在通常情況下,replication factor(副本數)默認爲 3, HDFS 的數據分佈策略是將兩份副本放在本地機架的兩個不同 DataNode 上,最後一個副本放在另外一個機架的一個 DataNode 上。

NameNode 基於機架感知的數據分佈策略並未考慮 DataNode 的磁盤空間利用率。這有效避免了將新的文件數據集中放置在一組擁有大量剩餘空間的 DataNodes 上,比如新擴容的 DataNodes。這又帶來另外一個問題,就是擴容新 DataNode 時導致數據分佈的嚴重不平衡。

爲了應對此類情況,HDFS 引入了一個平衡器工具(Balancer),在整個集羣平衡磁盤空間利用率。這個工具通過引入設置一個在 0 和 1 之間的閾值來判斷整個集羣是否達到平衡。

HDFS 對於磁盤均衡的定義如下:

對於每一個 DataNode 其磁盤利用率與整個集羣的平均利用率相比不超過設置的閾值偏差。

平衡器工作過程中確保不會減少副本總數,及其分佈的機架數。也就是原來三個副本分佈在兩個機架,被平衡後也還是三個副本分佈在兩個機架,但可能移動到不同的 DataNode 上了。爲了減少網絡帶寬佔用,會儘可能避免機架間拷貝數據。例如:副本 A1 和 A2 在 Rack1,A3 在 Rack2,若平衡器認爲 A1 所在 DataNode 磁盤利用率過高,需要移動 A1。在 Rack1 內找不到磁盤利用率低的其他 DataNode,則需要將 A1 移動到 Rack2。實際做法是直接從 Rack2 的 A3 複製一份得到 A4,並刪除 Rack1 上的 A1,這樣就避免了機架間複製。

複製管理

NameNode 努力確保每一個副本符合配置的 replication factor。假如 DataNode 宕機發生導致一些文件的 block 副本數變少,Namdenode 會發出複製命令給 DataNode,複製出新的副本以保持與配置的副本數一致。當宕機的 DataNode 恢復後重新加入集羣后會導致一些文件的副本數超出配置數,NameNode 會檢測到並刪除多餘的副本以節省存儲空間。NameNode 維護一個複製優先級隊列,對於副本不足的文件 block 按優先級排序,僅剩下一個副本的文件 block 享有最高的複製優先級。

性能設計

除了 NameNode 的單點和重啓過程影響可用性外,另一個擔憂因素是性能。 
讀操作基於內存訪問還好,寫操作中磁盤是一個瓶頸點。而 NameNode 支持大量 Client 的併發讀寫,對於大量的併發寫操作 NameNode 進行了優化。多線程情況下,當一個線程爲保存操作事務日誌發起一個 flush-and-sync 到磁盤文件的操作,其他線程只能等待。爲了優化此類情況,NameNode 將隨機寫轉換爲批量寫操作。當一個 NameNode 的線程初始化了一個 flush-and-sync 操作,所有當時的事務操作日誌被批量寫入文件。其餘的線程只需要檢查它們的事務是否被保存到了文件而不再需要再發起 flush-and-sync 操作。

總結

上面描述了 NameNode 提供的功能及其設計實現要點,最後我們簡單點評下它在架構設計上的權衡考量。首先 NameNode 作爲中心節點簡化了整體設計,但很顯然它也是個單點,會影響可用性。其次 NameNode 將所有元數據存儲在內存中,內存的容量決定了整個分佈式文件系統能支持文件數量,如果是大量的小文件場景也是個問題。而且 HDFS 基於 java 實現,java 針對大堆內存的 GC 優化也是個麻煩事。再次上面描述的 NameNode 的啓動過程看起來就很耗時,特別是在 FsImage 和 EditLog 都很大的情況下。而且在 NameNode 的啓動完成前整個 HDFS 是不可用的,所以 NameNode 即使是重啓也對整體的可用性有很大影響。

參考

[1] Hadoop Documentation. HDFS Architecture
[2] Robert Chansler, Hairong Kuang, Sanjay Radia, Konstantin Shvachko, and Suresh Srinivas. The Hadoop Distributed File System


轉載自:http://www.cnblogs.com/mindwind/p/4833101.html

發佈了3 篇原創文章 · 獲贊 7 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章