Hadoop分佈式文件系統(HDFS)是一種分佈式文件系統。它與現有的分佈式文件系統有許多類似之處。可是,與其餘分佈式文件系統的差別是值得咱們注意的:node
HDFS具備高度容錯能力,旨在部署在低成本硬件上。(高容錯)shell
HDFS提供對數據的高吞吐量訪問,適用於具備海量數據集的應用程序。(高吞吐量)瀏覽器
HDFS放寬了一些POSIX要求,以實現對文件系統數據的流式訪問。(流式訪問)安全
HDFS最初是做爲Apache Nutch網絡搜索引擎項目的基礎設施而構建的。HDFS是Apache Hadoop Core項目的一部分。bash
目標和假設服務器
硬件故障檢測:硬件故障是常態而非例外。Hadoop一般部署在低成本的硬件上,而且一般包含成百上千的服務器,每一個服務器都存儲文件系統數據的一部分。因爲存在大量的組件,而且每一個組件都具備不可忽略(non-trivial )的故障機率,這意味着HDFS的某些組件始終都不起做用。所以,故障檢測並快速恢復是HDFS的核心架構目標。網絡
流式訪問:HDFS更適合批處理而不是交互式使用,更加註重數據訪問的高吞吐量而不是數據訪問的低延遲。在HDFS上運行的應用程序須要對其數據集進行流式訪問。數據結構
海量數據集:運行在HDFS上的應用程序具備大型數據集,HDFS中的一個典型文件的大小是g到tb,所以,HDFS被調優爲支持大文件。它應該提供高聚合數據帶寬,並可擴展到單個集羣中的數百個節點。它應該在一個實例中支持數千萬個文件。架構
一致性模型:HDFS應用程序須要一個一次寫入屢次讀取的文件訪問模型。文件一旦建立、寫入和關閉,除了追加和截斷操做外,無須要更改。支持將內容追加到文件末尾,但沒法在任意點更新。該假設簡化了數據一致性問題並實現了高吞吐量數據訪問。MapReduce應用程序或Web爬蟲應用程序徹底適合此模型。負載均衡
移動計算比移動數據便宜:應用程序請求的計算若是在其操做的數據附近執行,效率會高得多。當數據集的大小很大時尤爲如此。這能夠最大限度地減小網絡擁塞並提升系統的總體吞吐量。所以更好的作法是將計算遷移到更靠近數據所在的位置,而不是將數據移動到運行應用程序的位置。HDFS爲應用程序提供了一些接口,使它們本身更接近數據所在的位置。
跨平臺和可移植:Hadoop使用Java語言開發,使得Hadoop具備良好的跨平臺性。
NameNode和DataNodes
HDFS具備主/從( master/slave)架構。HDFS集羣由一個NameNode和許多DataNode組成,NameNode是一個主服務器(master),管理文件系統名稱空間並管理客端對數據的訪問(NameNode在Hadoop集羣中充當u管家/u的角色)。此外集羣中每一個節點一般是一個DataNode,DataNode管理它們的節點上存儲的數據。
HDFS公開文件系統名稱空間,並容許用戶數據存儲在文件中。在內部,文件被分紅一個或多個塊(block),這些塊存儲在DataNode中。NameNode執行文件系統名稱空間的相關操做,如打開、關閉和重命名文件和目錄。它還肯定了塊到DataNode的映射(塊存儲到哪一個DataNode中)。數據節點負責服務來自文件系統客戶端的讀寫請求。數據節點還根據NameNode的指令執行塊建立、刪除和複製。
深刻理解Hadoop之HDFS架構
集羣中單一NameNode的結構大大簡化了系統的架構。NameNode是全部HDFS元數據的仲裁者和管理者,這樣,用戶數據永遠不會流過NameNode。
文件系統名稱空間(namespace)
HDFS支持傳統的層次型文件組織結構。用戶或者應用程序能夠建立目錄,而後將文件保存在這些目錄裏。文件系統名稱空間的層次結構和大多數現有的文件系統相似:用戶能夠建立、刪除、移動或重命名文件。當前,HDFS不支持用戶磁盤配額和訪問權限控制,也不支持硬連接和軟連接。可是HDFS架構並不妨礙實現這些特性。
NameNode負責維護文件系統的名稱空間,任何對文件系統名稱空間或屬性的修改都將被NameNode記錄下來。應用程序能夠設置HDFS保存的文件的副本數目。文件副本的數目稱爲文件的副本系數,這個信息也是由NameNode保存的。
若是想深刻了解HDFS文件系統名稱空間能夠查看這篇博文:http://leotse90.com/...
數據複製
HDFS被設計成可以在一個大集羣中跨機器可靠地存儲超大文件。它將每一個文件存儲成一系列的數據塊,除了最後一個,全部的數據塊都是一樣大小的。爲了容錯,文件的全部數據塊都會有副本。每一個文件的數據塊大小和副本系數都是可配置的。應用程序能夠指定某個文件的副本數目。副本系數能夠在文件建立的時候指定,也能夠在以後改變。HDFS中的文件都是一次性寫入的,而且嚴格要求在任什麼時候候只能有一個寫入者。
NameNode全權管理數據塊的複製,它週期性地從集羣中的每一個DataNode接收心跳信號(Heartbeat )和塊狀態報告(Blockreport)。
接收到心跳信號意味着該DataNode節點工做正常。
塊狀態報告包含了一個該Datanode上全部數據塊的列表。
深刻理解Hadoop之HDFS架構
副本存放: 最最開始的一步
副本的存放是HDFS可靠性和性能的關鍵。優化的副本存放策略是HDFS區分於其餘大部分分佈式文件系統的重要特性。這種特性須要作大量的調優,並須要經驗的積累。HDFS採用一種稱爲機架感知(rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。目前實現的副本存放策略只是在這個方向上的第一步。實現這個策略的短時間目標是驗證它在生產環境下的有效性,觀察它的行爲,爲實現更先進的策略打下測試和研究的基礎。
大型HDFS實例通常運行在跨越多個機架的計算機組成的集羣上,不一樣機架上的兩臺機器之間的通信須要通過交換機。在大多數狀況下,同一個機架內的兩臺機器間的帶寬會比不一樣機架的兩臺機器間的帶寬大。
經過一個機架感知的過程,NameNode能夠肯定每一個DataNode所屬的機架id。一個簡單但沒有優化的策略就是將副本存放在不一樣的機架上。這樣能夠有效防止當整個機架失效時數據的丟失,而且容許讀數據的時候充分利用多個機架的帶寬。這種策略設置能夠將副本均勻分佈在集羣中,有利於當組件失效狀況下的負載均衡。可是,由於這種策略的一個寫操做須要傳輸數據塊到多個機架,這增長了寫的代價。
在大多數狀況下,副本系數是3,HDFS的存放策略是將一個副本存放在本地機架的節點上,一個副本放在同一機架的另外一個節點上,最後一個副本放在不一樣機架的節點上。這種策略減小了機架間的數據傳輸,這就提升了寫操做的效率。機架的錯誤遠遠比節點的錯誤少,因此這個策略不會影響到數據的可靠性和可用性。於此同時,由於數據塊只放在兩個(不是三個)不一樣的機架上,因此此策略減小了讀取數據時須要的網絡傳輸總帶寬。在這種策略下,副本並非均勻分佈在不一樣的機架上。三分之一的副本在一個節點上,三分之二的副本在一個機架上,其餘副本均勻分佈在剩下的機架中,這一策略在不損害數據可靠性和讀取性能的狀況下改進了寫的性能。
副本選擇
爲了下降總體的帶寬消耗和讀取延時,HDFS會盡可能讓讀取程序讀取離它最近的副本。若是在讀取程序的同一個機架上有一個副本,那麼就讀取該副本。若是一個HDFS集羣跨越多個數據中心,那麼客戶端也將首先讀本地數據中心的副本。(就近原則)
安全模式
NameNode啓動後會進入一個稱爲安全模式的特殊狀態。處於安全模式的NameNode是不會進行數據塊的複製的。NameNode從全部的 DataNode接收心跳信號和塊狀態報告。塊狀態報告包括了某個DataNode全部的數據塊列表。每一個數據塊都有一個指定的最小副本數。當NameNode檢測確認某個數據塊的副本數目達到這個最小值,那麼該數據塊就會被認爲是副本安全(safely replicated)的;在必定百分比(這個參數可配置)的數據塊被NameNode檢測確認是安全以後(加上一個額外的30秒等待時間),NameNode將退出安全模式狀態。接下來它會肯定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊複製到其餘DataNode上。
文件系統元數據的持久化
NameNode上保存着HDFS的DataNode空間。對於任何對文件系統元數據產生修改的操做,NameNode都會使用一種稱爲EditLog的事務日誌記錄下來。例如,在HDFS中建立一個文件,NameNode就會在Editlog中插入一條記錄來表示;一樣地,修改文件的副本系數也將往Editlog插入一條記錄。NameNode在本地操做系統的文件系統中存儲這個Editlog。整個文件系統的DataNode空間,包括數據塊到文件的映射、文件的屬性等,都存儲在一個稱爲FsImage的文件中,這個文件也是放在NameNode所在的本地文件系統上。
NameNode在內存中保存着整個文件系統的DataNode空間和文件數據塊映射(Blockmap)的映像。這個關鍵的元數據結構設計得很緊湊,於是一個有4G內存的NameNode足夠支撐大量的文件和目錄。當NameNode啓動時,它從硬盤中讀取Editlog和FsImage,將全部Editlog中的事務做用在內存中的FsImage上,並將這個新版本的FsImage從內存中保存到本地磁盤上,而後刪除舊的Editlog,由於這個舊的Editlog的事務都已經做用在FsImage上了。這個過程稱爲一個檢查點(checkpoint)。在當前實現中,檢查點只發生在NameNode啓動時,在不久的未來將實現支持週期性的檢查點。
Datanode將HDFS數據以文件的形式存儲在本地的文件系統中,它並不知道有關HDFS文件的信息。它把每一個HDFS數據塊存儲在本地文件系統的一個單獨的文件中。Datanode並不在同一個目錄建立全部的文件,實際上,它用試探的方法來肯定每一個目錄的最佳文件數目,而且在適當的時候建立子目錄。在同一個目錄中建立全部的本地文件並非最優的選擇,這是由於本地文件系統可能沒法高效地在單個目錄中支持大量的文件。當一個Datanode啓動時,它會掃描本地文件系統,產生一個這些本地文件對應的全部HDFS數據塊的列表,而後做爲報告發送到NameNode,這個報告就是塊狀態報告。
通信協議
全部的HDFS通信協議都是創建在TCP/IP協議之上。客戶端經過一個可配置的TCP端口鏈接到NameNode,經過ClientProtocol協議與NameNode交互。而Datanode使用DatanodeProtocol協議與NameNode交互。一個遠程過程調用(RPC)模型被抽象出來封裝ClientProtocol和Datanodeprotocol協議。在設計上,NameNode不會主動發起RPC,而是響應來自客戶端或 Datanode 的RPC請求。
健壯性
HDFS的主要目標就是即便在出錯的狀況下也要保證數據存儲的可靠性。常見的三種出錯狀況是:NameNode出錯, Datanode出錯和網絡割裂(network partitions)。
磁盤數據錯誤,心跳檢測和從新複製
每一個Datanode節點週期性地向NameNode發送心跳信號。網絡割裂可能致使一部分Datanode跟NameNode失去聯繫。NameNode經過心跳信號的缺失來檢測這一狀況,並將這些近期再也不發送心跳信號Datanode標記爲宕機,不會再將新的IO請求發給它們。任何存儲在宕機Datanode上的數據將再也不有效。Datanode的宕機可能會引發一些數據塊的副本系數低於指定值,NameNode不斷地檢測這些須要複製的數據塊,一旦發現就啓動複製操做。在下列狀況下,可能須要從新複製:某個Datanode節點失效,某個副本遭到損壞,Datanode上的硬盤錯誤,或者文件的副本系數增大。
集羣均衡
HDFS的架構支持數據均衡策略。若是某個Datanode節點上的空閒空間低於特定的臨界點,按照均衡策略系統就會自動地將數據從這個Datanode移動到其餘空閒的Datanode。當對某個文件的請求忽然增長,那麼也可能啓動一個計劃建立該文件新的副本,而且同時從新平衡集羣中的其餘數據。這些均衡策略目前尚未實現。
數據完整性
從某個Datanode獲取的數據塊有多是損壞的,損壞多是由Datanode的存儲設備錯誤、網絡錯誤或者軟件bug形成的。HDFS客戶端軟件實現了對HDFS文件內容的校驗和(checksum)檢查。當客戶端建立一個新的HDFS文件,會計算這個文件每一個數據塊的校驗和,並將校驗和做爲一個單獨的隱藏文件保存在同一個HDFSDataNode空間下。當客戶端獲取文件內容後,它會檢驗從Datanode獲取的數據跟相應的校驗和文件中的校驗和是否匹配,若是不匹配,客戶端能夠選擇從其餘Datanode獲取該數據塊的副本。
元數據磁盤錯誤
FsImage和Editlog是HDFS的核心數據結構。若是這些文件損壞了,整個HDFS實例都將失效。於是,NameNode能夠配置成支持維護多個FsImage和Editlog的副本。任何對FsImage或者Editlog的修改,都將同步到它們的副本上。這種多副本的同步操做可能會下降NameNode每秒處理的DataNode空間事務數量。然而這個代價是能夠接受的,由於即便HDFS的應用是數據密集的,它們也非元數據密集的。當NameNode重啓的時候,它會選取最近的完整的FsImage和Editlog來使用。
增長故障恢復能力的另外一個選擇是使用多個NameNode 在NFS上使用共享存儲或使用分佈式編輯日誌(稱爲Journal)來啓用高可用性。後者是推薦的方法。
快照
快照支持在特定時刻存儲數據副本。快照功能的一種用途能夠是將損壞的HDFS實例回滾到先前已知的良好時間點。
數據組織
數據塊
HDFS被設計成支持大文件,適用HDFS的是那些須要處理大規模的數據集的應用。這些應用都是隻寫入數據一次,但卻讀取一次或屢次,而且讀取速度應能知足流式讀取的須要。HDFS支持文件的「一次寫入屢次讀取」語義。一個典型的數據塊大小是128MB。於是,HDFS中的文件老是按照128M被切分紅不一樣的塊,每一個塊儘量地存儲於不一樣的Datanode中。
流水線複製
當客戶端向HDFS文件寫入數據的時候,一開始是寫到本地臨時文件中。假設該文件的副本系數設置爲3,當本地臨時文件累積到一個數據塊的大小時,客戶端會從NameNode獲取一個Datanode列表用於存放副本。而後客戶端開始向第一個Datanode傳輸數據,第一個Datanode一小部分一小部分(4 KB)地接收數據,將每一部分寫入本地倉庫,並同時傳輸該部分到列表中第二個Datanode節點。第二個Datanode也是這樣,一小部分一小部分地接收數據,寫入本地倉庫,並同時傳給第三個Datanode。最後,第三個Datanode接收數據並存儲在本地。所以,Datanode能流水線式地從前一個節點接收數據,並在同時轉發給下一個節點,數據以流水線的方式從前一個Datanode複製到下一個。
可訪問性
能夠經過多種不一樣方式從應用程序訪問HDFS。本地,HDFS 爲應用程序提供了FileSystem Java API。一本Java API的C語言包裝和REST API也是可用的。此外,還有HTTP瀏覽器,也可用於瀏覽HDFS實例的文件。經過使用NFS網關,HDFS能夠做爲客戶端本地文件系統的一部分進行安裝。
FS Shell
HDFS以文件和目錄的形式組織用戶數據。它提供了一個命令行的接口(FS Shell)讓用戶與HDFS中的數據進行交互。命令的語法和用戶熟悉的其餘shell(例如 bash, csh)工具相似。下面是一些動做/命令的示例:
深刻理解Hadoop之HDFS架構
FS shell適用於須要腳本語言與存儲數據交互的應用程序。
DFSAdmin
典型的HDFS安裝配置Web服務器以經過可配置的TCP端口公開HDFS命名空間。這容許用戶使用Web瀏覽器導航HDFS命名空間並查看其文件的內容。
深刻理解Hadoop之HDFS架構
存儲空間回收
文件的刪除和恢復
若是啓用了回收站配置,當用戶或應用程序刪除某個文件時,這個文件並無馬上從HDFS中刪除。實際上,HDFS會將這個文件重命名轉移到/trash目錄(/user/username/.Trash)。只要文件還在/trash目錄中,該文件就能夠被迅速地恢復。文件在/trash中保存的時間是可配置的,當超過這個時間時,NameNode就會將該文件從DataNode空間中刪除。刪除文件會使得該文件相關的數據塊被釋放。注意,從用戶刪除文件到HDFS空閒空間的增長之間會有必定時間的延遲。
如下是一個示例,它將顯示FS Shell如何從HDFS中刪除文件。咱們在目錄delete下建立了2個文件(test1和test2)
$ hadoop fs -mkdir -p delete/test1
$ hadoop fs -mkdir -p delete/test2
$ hadoop fs -ls delete/
Found 2 items
drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:39 delete/test1
drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:40 delete/test2
咱們將刪除文件test1。下面的註釋顯示該文件已移至/trash目錄。
$ hadoop fs -rm -r delete/test1
Moved: hdfs://localhost:8020/user/hadoop/delete/test1 to trash at: hdfs://localhost:8020/user/hadoop/.Trash/Current
如今咱們將使用skipTrash選項刪除該文件,該選項不會將文件發送到Trash。它將從HDFS中徹底刪除。
$ hadoop fs -rm -r -skipTrash delete/test2
Deleted delete/test2
咱們如今能夠看到Trash目錄只包含文件test1。
$ hadoop fs -ls .Trash/Current/user/hadoop/delete/
Found 1 items\
drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:39 .Trash/Current/user/hadoop/delete/test1
所以文件test1進入垃圾箱並永久刪除文件test2。
減小副本系數
當一個文件的副本系數被減少後,NameNode會選擇過剩的副本刪除。下次心跳檢測時會將該信息傳遞給Datanode。Datanode遂即移除相應的數據塊,集羣中的空閒空間加大。一樣,在調用setReplication API結束和集羣中空閒空間增長間會有必定的延遲。