一、概述node
小文件是指文件size小於HDFS上block大小的文件。這樣的文件會給Hadoop的擴展性和性能帶來嚴重問題。首先,在HDFS中,任何block,文件或者目錄在內存中均以對象的形式存儲,每一個對象約佔150byte,若是有1000 0000個小文件,每一個文件佔用一個block,則namenode大約須要2G空間。若是存儲1億個文件,則namenode須要20G空間(見參考資料[1][4][5])。這樣namenode內存容量嚴重製約了集羣的擴展。 其次,訪問大量小文件速度遠遠小於訪問幾個大文件。HDFS最初是爲流式訪問大文件開發的,若是訪問大量小文件,須要不斷的從一個datanode跳到另外一個datanode,嚴重影響性能。最後,處理大量小文件速度遠遠小於處理同等大小的大文件的速度。每個小文件要佔用一個slot,而task啓動將耗費大量時間甚至大部分時間都耗費在啓動task和釋放task上。shell
本文首先介紹了hadoop自帶的解決小文件問題的方案(以工具的形式提供),包括Hadoop Archive,Sequence file和CombineFileInputFormat;而後介紹了兩篇從系統層面解決HDFS小文件的論文,一篇是中科院計算所2009年發表的,用以解決HDFS上存儲地理信息小文件的方案;另外一篇是IBM於2009年發表的,用以解決HDFS上存儲ppt小文件的方案。socket
二、HDFS文件讀寫流程工具
在正式介紹HDFS小文件存儲方案以前,咱們先介紹一下當前HDFS上文件存取的基本流程。oop
(1) 讀文件流程性能
1)client端發送讀文件請求給namenode,若是文件不存在,返回錯誤信息,不然,將該文件對應的block及其所在datanode位置發送給clientspa
2) client收到文件位置信息後,與不一樣datanode創建socket鏈接並行獲取數據。orm
(2) 寫文件流程對象
1)client端發送寫文件請求,namenode檢查文件是否存在,若是已存在,直接返回錯誤信息,不然,發送給client一些可用datanode節點排序
2)client將文件分塊,並行存儲到不一樣節點上datanode上,發送完成後,client同時發送信息給namenode和datanode
3)namenode收到的client信息後,發送確信信息給datanode
4)datanode同時收到namenode和datanode的確認信息後,提交寫操做。
三、Hadoop自帶的解決方案
對於小文件問題,Hadoop自己也提供了幾個解決方案,分別爲:Hadoop Archive,Sequence file和CombineFileInputFormat。
(1) Hadoop Archive
Hadoop Archive或者HAR,是一個高效地將小文件放入HDFS塊中的文件存檔工具,它可以將多個小文件打包成一個HAR文件,這樣在減小namenode內存使用的同時,仍然容許對文件進行透明的訪問。
對某個目錄/foo/bar下的全部小文件存檔成/outputdir/ zoo.har:
hadoop archive -archiveName zoo.har -p /foo/bar /outputdir
固然,也能夠指定HAR的大小(使用-Dhar.block.size)。
HAR是在Hadoop file system之上的一個文件系統,所以全部fs shell命令對HAR文件都可用,只不過是文件路徑格式不同,HAR的訪問路徑能夠是如下兩種格式:
har://scheme-hostname:port/archivepath/fileinarchive
har:///archivepath/fileinarchive(本節點)
能夠這樣查看HAR文件存檔中的文件:
hadoop dfs -ls har:///user/zoo/foo.har
輸出:
har:///user/zoo/foo.har/hadoop/dir1
har:///user/zoo/foo.har/hadoop/dir2
使用HAR時須要兩點,第一,對小文件進行存檔後,原文件並不會自動被刪除,須要用戶本身刪除;第二,建立HAR文件的過程其實是在運行一個mapreduce做業,於是須要有一個hadoop集羣運行此命令。
此外,HAR還有一些缺陷:第一,一旦建立,Archives便不可改變。要增長或移除裏面的文件,必須從新建立歸檔文件。第二,要歸檔的文件名中不能有空格,不然會拋出異常,能夠將空格用其餘符號替換(使用-Dhar.space.replacement.enable=true 和-Dhar.space.replacement參數)。
(2) Sequence file
sequence file由一系列的二進制key/value組成,若是爲key小文件名,value爲文件內容,則能夠將大批小文件合併成一個大文件。
Hadoop-0.21.0中提供了SequenceFile,包括Writer,Reader和SequenceFileSorter類進行寫,讀和排序操做。若是hadoop版本低於0.21.0的版本,實現方法可參見[3]。
(3)CombineFileInputFormat
CombineFileInputFormat是一種新的inputformat,用於將多個文件合併成一個單獨的split,另外,它會考慮數據的存儲位置。