- Hadoop大數據技術開發實戰
- 張偉洋
- 3177字
- 2020-03-06 11:48:37
4.1 HDFS簡介
HDFS(Hadoop Distributed File System)是Hadoop項目的核心子項目,在大數據開發中通過分布式計算對海量數據進行存儲與管理。它基于流數據模式訪問和處理超大文件的需求而開發,可以運行在廉價的商用服務器上,為海量數據提供了不怕故障的存儲方法,進而為超大數據集的應用處理帶來了很多便利。
下面是HDFS的一些顯著特征:
- HDFS非常適合使用商用硬件進行分布式存儲和分布式處理。它具有容錯性、可擴展性,并且擴展極其簡單。
- HDFS具有高度可配置性。大多數情況下,需要僅針對非常大的集群調整默認配置。
- HDFS是Hadoop的核心框架,而Hadoop是用Java編寫的,因此可以運行于所有主流平臺上。
- 支持類似Shell的命令直接與HDFS交互。
- HDFS內置了Web服務器,可以輕松檢查集群的當前狀態。
4.1.1 設計目標
HDFS的主要設計目標如下。
1. 硬件故障
硬件故障是常態,而非例外。HDFS集群可能由數百或數千臺服務器組成,每臺服務器都存儲文件系統數據的一部分,且每臺服務器都有很大的故障概率。因此,故障檢測和快速、自動地從故障中恢復是HDFS的核心架構目標。
2. 流式數據訪問
在HDFS上運行的應用程序需要對其數據集進行流式訪問,這與運行在一般文件系統上的應用不同。HDFS更適合批量處理,而不是用戶的交互使用,它更加強調數據訪問的高吞吐量,而不是數據訪問的低延遲。
3. 大型數據集
HDFS是一個支持大型數據集的文件系統,一個典型的HDFS數據文件可以從千兆字節到兆兆字節不等,可以為具有數百個節點的集群提供高聚合的數據帶寬和規模,同時承載千萬個文件。
4. 簡單一致性模型
HDFS遵循簡單一致性模型,一次寫入,多次讀取。即文件一旦被建立、寫入、關閉,就不能被改變,更不能從文件任意位置進行修改,以此來保證數據的一致性。Hadoop 2.x以后,支持在文件末尾追加內容。
5. 移動計算比移動數據容易
HDFS被設計為能更好地將計算遷移到更接近數據的位置,而不是將數據移動到應用程序運行的位置,這樣應用程序的計算效率會更高。HDFS為應用程序提供接口,使其更接近數據所在的位置。
6. 平臺的可移植性
HDFS被設計為可以從一個平臺輕松地移植到另一個平臺,從而使HDFS能夠作為大型應用程序的首選平臺。
4.1.2 總體架構
HDFS是使用Java語言構建的系統,任何支持Java的計算機都可以運行HDFS,HDFS集群的總體架構如圖4-1所示。

圖4-1 HDFS集群的總體架構
HDFS是一個典型的主/從(Master/Slave)架構的分布式系統。一個HDFS集群由一個元數據節點(稱為NameNode)和一些數據節點(稱為DataNode)組成。NameNode是HDFS的主節點,是一個用來管理文件元數據(文件名稱、大小、存儲位置等)和處理來自客戶端的文件訪問請求的主服務器;DataNode是HDFS的從節點,用來管理對應節點的數據存儲,即實際文件數據存儲于DataNode上,而DataNode中的數據則保存在本地磁盤。
當HDFS系統啟動后,NameNode上會啟動一個名稱為“NameNode”的進程,DataNode上會啟動一個名稱為“DataNode”的進程。
典型的HDFS集群部署是有一臺專用的計算機只運行NameNode進程,集群中的其他計算機都運行DataNode進程。HDFS架構并不排除在同一臺計算機上運行多個DataNode進程,但在實際部署中很少出現這種情況。
HDFS集群中單個NameNode的存在極大地簡化了系統的體系結構。NameNode是HDFS元數據的仲裁者和存儲庫。該系統的設計方式是,用戶數據永遠不會流經NameNode。
此外,還有一個重要組件稱為SecondaryNameNode,4.1.3節將對HDFS各組件進行詳細講解。
4.1.3 主要組件
HDFS系統的主要構成組件如下。
1. 數據塊(Block)
HDFS中的文件是以數據塊(Block)的形式存儲的,默認最基本的存儲單位是128 MB(Hadoop 1.x為64 MB)的數據塊。也就是說,存儲在HDFS中的文件都會被分割成128 MB一塊的數據塊進行存儲,如果文件本身小于一個數據塊的大小,則按實際大小存儲,并不占用整個數據塊空間。
HDFS的數據塊之所以會設置這么大,其目的是減少尋址開銷。數據塊數量越多,尋址數據塊所耗的時間就越多。當然也不會設置過大,MapReduce中的Map任務通常一次只處理一個塊中的數據,如果任務數太少,作業的運行速度就會比較慢(MapReduce將在第5章講解)。
HDFS的每一個數據塊默認都有三個副本,分別存儲在不同的DataNode上,以實現容錯功能。因此,若數據塊的某個副本丟失并不會影響對數據塊的訪問。數據塊大小和副本數量可在配置文件中更改。HDFS數據塊的存儲結構如圖4-2所示。

圖4-2 HDFS數據塊的存儲結構
2. NameNode
NameNode是HDFS中存儲元數據(文件名稱、大小和位置等信息)的地方,它將所有文件和文件夾的元數據保存在一個文件系統目錄樹中,任何元數據信息的改變,NameNode都會記錄。HDFS中的每個文件都被拆分為多個數據塊存放,這種文件與數據塊的對應關系也存儲在文件系統目錄樹中,由NameNode維護。
NameNode還存儲數據塊到DataNode的映射信息,這種映射信息包括:數據塊存放在哪些DataNode上、每個DataNode上保存了哪些數據塊。
NameNode也會周期性地接收來自集群中DataNode的“心跳”和“塊報告”。通過“心跳”與DataNode保持通信,監控DataNode的狀態(活著還是宕機),若長時間接收不到“心跳”信息,NameNode會認為DataNode已經宕機,從而做出相應的調整策略。“塊報告”包含了DataNode上所有數據塊的列表信息。
3. DataNode
DataNode是HDFS中真正存儲數據的地方??蛻舳丝梢韵駾ataNode請求寫入或讀取數據塊,DataNode還在來自NameNode的指令下執行塊的創建、刪除和復制,并且周期性地向NameNode匯報數據塊信息。
4. SecondaryNameNode
SecondaryNameNode用于幫助NameNode管理元數據,從而使NameNode能夠快速、高效地工作。它并不是第二個NameNode,僅是NameNode的一個輔助工具。
HDFS的元數據信息主要存儲于兩個文件中:fsimage和edits。fsimage是文件系統映射文件,主要存儲文件元數據信息,其中包含文件系統所有目錄、文件信息以及數據塊的索引;edits是HDFS操作日志文件,HDFS對文件系統的修改日志會存儲到該文件中。
當NameNode啟動時,會從文件fsimage中讀取HDFS的狀態,也會對文件fsimage和edits進行合并,得到完整的元數據信息,隨后會將新HDFS狀態寫入fsimage。但是在繁忙的集群中,edits文件會隨著時間的推移變得非常大,這就導致NameNode下一次啟動的時間會非常長。為了解決這個問題,則產生了SecondaryNameNode,SecondaryNameNode會定期協助NameNode合并fsimage和edits文件,并使edits文件的大小保持在一定的限制內。SecondaryNameNode通常與NameNode在不同的計算機上運行,因為它的內存需求與NameNode相同,這樣可以減輕NameNode所在計算機的壓力。
SecondaryNameNode的工作流程如圖4-3所示。

圖4-3 SecondaryNameNode的工作流程
首先,當SecondaryNameNode準備從NameNode上獲取元數據時,會通知NameNode暫停對文件edits的寫入。NameNode收到通知后,會停止寫入edits文件,而是將新的操作日志信息寫入到一個新的文件edits.new中。
然后,SecondaryNameNode通過http get方式將NameNode的元數據文件edits和fsimage獲取到本地,并將其合并為一個新的文件fsimage.ckpt。
最后,SecondaryNameNode把新的文件fsimage.ckpt通過http post方式發回NameNode。NameNode收到SecondaryNameNode發回的新文件fsimage.ckpt后,用該文件覆蓋掉原來的fsimage文件,并刪除原有的edits文件,同時將文件edits.new重命名為edits,將文件fsimage.ckpt重命名為fsimage。
上述操作避免了NameNode日志的無限增長,從而加速了NameNode的啟動過程。
4.1.4 文件讀寫
如圖4-4所示,當客戶端需要讀取文件時,首先向NameNode發起讀請求,NameNode收到請求后,會將請求文件的數據塊在DataNode中的具體位置(元數據信息)返回給客戶端,客戶端根據文件數據塊的位置,直接找到相應的DataNode發起讀請求。

圖4-4 HDFS讀數據流程
如圖4-5所示,當客戶端需要寫文件時,首先向NameNode發起寫請求,將需要寫入的文件名、文件大小等信息告訴NameNode。NameNode會將文件信息記錄到本地,同時會驗證客戶端的寫入權限,若驗證通過,會向客戶端返回文件數據塊能夠存放在DataNode上的存儲位置信息,然后客戶端直接向DataNode的相應位置寫入數據塊。被寫入數據塊的DataNode也會將數據塊備份到其他DataNode上。

圖4-5 HDFS寫數據流程
舉個例子,我們可以把NameNode想象成是一個倉庫管理員,管理倉庫中的商品;DataNode想象成是一個倉庫,用于存儲商品,而商品就是我們所說的數據。倉庫管理員只有一個,而倉庫可以有多個。當需要從倉庫中獲取商品時,需要先詢問倉庫管理員,獲得倉庫管理員的同意,并且得到商品所在倉庫的具體位置(例如,在1號倉庫的1號貨架上),然后根據位置信息直接去對應的倉庫中的相應貨架上取得商品。當需要向倉庫中存入商品時,同樣需要先詢問倉庫管理員,獲得倉庫管理員的同意,并且得到倉庫管理員提供的商品能夠存放的具體位置,然后根據位置信息直接去對應的倉庫中的相應貨架上存入商品。
此外,用戶可以使用多種客戶端接口對HDFS發起讀/寫操作,包括命令行接口、代碼API接口和瀏覽器接口,使用非常方便,而不需要考慮HDFS的內部實現。本章后續將詳細講解HDFS各種接口的使用。