分布式文件系統HDFS解析
Hadoop 主要由HDFS和MapReduce 引擎兩部分組成。最底部是HDFS,它存儲Hadoop 集群中所有存儲節點上的文件。HDFS 的上一層是MapReduce 引擎,該引擎由JobTrackers 和TaskTrackers組成。
一、HDFS基本概念
1、數據塊
HDFS默認的最基本的存儲單位是64M的數據塊,這個數據塊可以理解和一般的文件里面的分塊是一樣的,不同于普通文件系統的是,HDFS中,如果一個文件小于一個數據塊的大小,那么并不占用整個數據塊存儲空間。
2、元數據節點和數據節點
元數據節點是用來管理文件系統的命名空間,它將所有的文件和文件夾的元數據保存在一個文件系統樹中。 數據節點是用來存儲數據文件的。 從元數據節點(secondarynamenode)不是我們所想象的元數據節點的備用節點,其實它主要的功能是主要功能就是周期性將元數據節點的命名空間鏡像文件和修改日志合并,以防日志文件過大。
3、HDFS中的數據流
讀文件
客戶端(client)用FileSystem的open()函數打開文件,DistributedFileSystem用RPC調用元數據節點,得到文件的數據塊信息。對于每一個數據塊,元數據節點返回保存數據塊的數據節點的地址。DistributedFileSystem返回FSDataInputStream給客戶端,用來讀取數據。客戶端調用stream的read()函數開始讀取數據。DFSInputStream連接保存此文件第一個數據塊的最近的數據節點。Data從數據節點讀到客戶端(client),當此數據塊讀取完畢時,DFSInputStream關閉和此數據節點的連接,然后連接此文件下一個數據塊的最近的數據節點。當客戶端讀取完畢數據的時候,調用FSDataInputStream的close函數。
整個過程如圖所示:

寫文件
客戶端調用create()來創建文件,DistributedFileSystem用RPC調用元數據節點,在文件系統的命名空間中創建一個新的文件。元數據節點首先確定文件原來不存在,并且客戶端有創建文件的權限,然后創建新文件。DistributedFileSystem返回DFSOutputStream,客戶端用于寫數據??蛻舳碎_始寫入數據,DFSOutputStream將數據分成塊,寫入data queue。Data queue由Data Streamer讀取,并通知元數據節點分配數據節點,用來存儲數據塊(每塊默認復制3塊)。分配的數據節點放在一個pipeline里。Data Streamer將數據塊寫入pipeline中的第一個數據節點。第一個數據節點將數據塊發送給第二個數據節點。第二個數據節點將數據發送給第三個數據節點。DFSOutputStream為發出去的數據塊保存了ack queue,等待pipeline中的數據節點告知數據已經寫入成功。如果數據節點在寫入的過程中失敗:關閉pipeline,將ack queue中的數據塊放入data queue的開始。
整個過程如圖所示:

二、HDFS的優缺點
2.1 HDFS的優點
1)處理超大文件
這里的超大文件通常是指百MB、設置數百TB大小的文件。目前在實際應用中,HDFS已經能用來存儲管理PB級的數據了。
2)流式的訪問數據
HDFS的設計建立在更多地響應"一次寫入、多次讀寫"任務的基礎上。這意味著一個數據集一旦由數據源生成,就會被復制分發到不同的存儲節點中,然后響應各種各樣的數據分析任務請求。在多數情況下,分析任務都會涉及數據集中的大部分數據,也就是說,對HDFS來說,請求讀取整個數據集要比讀取一條記錄更加高效。
3)運行于廉價的商用機器集群上
Hadoop設計對硬件需求比較低,只須運行在低廉的商用硬件集群上,而無需昂貴的高可用性機器上。廉價的商用機也就意味著大型集群中出現節點故障情況的概率非常高。這就要求設計HDFS時要充分考慮數據的可靠性,安全性及高可用性。
2.2 HDFS的缺點
1)不適合低延遲數據訪問
如果要處理一些用戶要求時間比較短的低延遲應用請求,則HDFS不適合。HDFS是為了處理大型數據集分析任務的,主要是為達到高的數據吞吐量而設計的,這就可能要求以高延遲作為代價。
改進策略:對于那些有低延時要求的應用程序,HBase是一個更好的選擇。通過上層數據管理項目來盡可能地彌補這個不足。在性能上有了很大的提升,它的口號就是goes real time。使用緩存或多master設計可以降低client的數據請求壓力,以減少延時。還有就是對HDFS系統內部的修改,這就得權衡大吞吐量與低延時了,HDFS不是萬能的銀彈。
2)無法高效存儲大量小文件
因為Namenode把文件系統的元數據放置在內存中,所以文件系統所能容納的文件數目是由Namenode的內存大小來決定。一般來說,每一個文件、文件夾和Block需要占據150字節左右的空間,所以,如果你有100萬個文件,每一個占據一個Block,你就至少需要300MB內存。當前來說,數百萬的文件還是可行的,當擴展到數十億時,對于當前的硬件水平來說就沒法實現了。還有一個問題就是,因為Map task的數量是由splits來決定的,所以用MR處理大量的小文件時,就會產生過多的Maptask,線程管理開銷將會增加作業時間。舉個例子,處理10000M的文件,若每個split為1M,那就會有10000個Maptasks,會有很大的線程開銷;若每個split為100M,則只有100個Maptasks,每個Maptask將會有更多的事情做,而線程的管理開銷也將減小很多。
改進策略:要想讓HDFS能處理好小文件,有不少方法。
利用SequenceFile、MapFile、Har等方式歸檔小文件,這個方法的原理就是把小文件歸檔起來管理,HBase就是基于此的。對于這種方法,如果想找回原來的小文件內容,那就必須得知道與歸檔文件的映射關系。
橫向擴展,一個Hadoop集群能管理的小文件有限,那就把幾個Hadoop集群拖在一個虛擬服務器后面,形成一個大的Hadoop集群。google也是這么干過的。
多Master設計,這個作用顯而易見了。正在研發中的GFS II也要改為分布式多Master設計,還支持Master的Failover,而且Block大小改為1M,有意要調優處理小文件啊。
附帶個Alibaba DFS的設計,也是多Master設計,它把Metadata的映射存儲和管理分開了,由多個Metadata存儲節點和一個查詢Master節點組成。
3)不支持多用戶寫入及任意修改文件
在HDFS的一個文件中只有一個寫入者,而且寫操作只能在文件末尾完成,即只能執行追加操作。目前HDFS還不支持多個用戶對同一文件的寫操作,以及在文件任意位置進行修改。