HDFS存储大量小文件的问题及解决方案
1.存儲大量小文件存在的問題
大量小文件的存在勢必占用大量的 NameNode 內存
HDFS 中的每一個文件、目錄以及文件塊,在 NameNode 內存都會有記錄,每一條記錄大約占用150字節的內存空間(該大小與文件、目錄及文件塊的大小無關),namenode的內存就會成為HDFS 的橫向擴展能力的一個限制因素。
如果我們使用 MapReduce 任務來處理這些小文件,因為每個 Map 會處理一個 HDFS 塊;這會導致程序啟動大量的 Map 來處理這些小文件,( 讀取小文件數據的任務執行時,消耗過多的集群資源。因為map task在執行的時候一般只處理1個文件,如果這個時候要讀取的文件過多,就會造成大量的map task啟動。) 雖然這些小文件總的大小并非很大,卻占用了集群的大量資源!
2.大量小文件產生的情況
- **實時流處理:**比如我們使用 Spark Streaming 從外部數據源接收數據,然后經過 ETL 處理之后存儲到 HDFS 中。這種情況下在每個 Job 中會產生大量的小文件。
- **MapReduce 產生:**我們使用 Hive 查詢一張含有海量數據的表,然后存儲在另外一張表中,而這個查詢只有簡單的過濾條件(比如 select * from iteblog where from = ‘hadoop’),這種情況只會啟動大量的 Map 來處理,這種情況可能會產生大量的小文件。也可能 Reduce 設置不合理,產生大量的小文件。
- **數據本身的特點:**比如我們在 HDFS 上存儲大量的圖片、短視頻、短音頻等文件,由于這些文件的特點,而且數量眾多,也可能給 HDFS 大量災難。
Hadoop提供的解決方案
分別為:Hadoop Archive,Sequence file和CombineFileInputFormat。
(1)Hadoop Archive
Hadoop Archive或者HAR,是一個高效地將小文件放入HDFS塊中的文件存檔工具,它能夠將多個小文件打包成一個HAR文件,這樣在減少namenode內存使用的同時,仍然允許對文件進行透明的訪問。
從上圖我們可以看出,Hadoop在歸檔文件時通過二層索引文件的查找,進行最終文件的讀取。所以在效率上會比普通HDFS讀取文件慢一些。
對某個目錄/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
創建存檔文件的問題:
1、存檔文件的源文件目錄以及源文件都不會自動刪除需要手動刪除
2、存檔的過程實際是一個mapreduce過程,所以需要需要hadoop的mapreduce的支持
3、存檔文件本身不支持壓縮
4、存檔文件一旦創建便不可修改,要想從中刪除或者增加文件,必須重新建立存檔文件
5、創建存檔文件會創建原始文件的副本,所以至少需要有與存檔文件容量相同的磁盤空間
6、要歸檔的文件名中不能有空格,否則會拋出異常,可以將空格用其他符號替換(使用-Dhar.space.replacement.enable=true 和-Dhar.space.replacement參數)。
7、對于一個mapreduce任務來說,如果使用HAR文件作為其輸入,仍舊是其中每個小文件對應一個map task,效率低下。所以,HAR files最好是用于文件歸檔。
(2)Sequence File
sequence file由一系列的二進制key/value組成,其中key為小文件名,value為文件內容,則可以將大批小文件合并成一個大文件,通過改變文件的寫出方式,寫入到SequenceFile格式的文件中。這主要是因為SequenceFile獨有的存儲格式決定了它可以很好的滿足小文件存儲的需求。SequenceFile文件內部存儲數據的方式是以下面key-value的形式拼接而成。
因為考慮到小文件中的內容少,在這里我們可以以文件名作為key,文件內容作為value,直接寫到SequenceFile中。
通常對于"小文件問題"的回應會是:使用序列文件(SequenceFile)。這種方法的思路是,使用文件名(filename)作為key,并且文件內容(file contents)作為value。
將大量小文件放入一個單一的SequenceFile,流式處理操作SequenceFile的兩個優勢:
(3)CombineFileInputFormat
CombineFileInputFormat是一種新的inputformat,用于將多個文件合并成一個單獨的split。功能,是將一個目錄(可能包括多個小文件,不包括子目錄)作為一個map的輸入,而不是通常使用一個文件作為輸入。
總結
以上是生活随笔為你收集整理的HDFS存储大量小文件的问题及解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2010年5月系统集成项目管理工程师上午
- 下一篇: 这四款录屏工具,也许是电脑录屏软件中免费