Hadoop存档
每个文件均按块方式存储,每个块的元数据存储在namenode的内存中,因此 Hadoop存储小文件会非常低效。因为大量的小文件会耗尽namenode中的大部分内存。但注意,存储小文件所需的磁盘容量和存储这些文件原始内容所需要的磁盘空间相比也不会增多。例如,一个1 MB的文件以大小为128 MB的块存储,使用的是1 MB的磁盘空间,而不是128 MB。
Hadoop存档文件或HAR文件,是一个更高效的文件存档工具,它将文件存入HDFS块,在减少namenode内存使用的同时,还能允许对文件进行透明的访问。具体说来,Hadoop存档文件可以用作MapReduce的输入。
使用Hadoop存档工具
Hadoop存档是通过archive工具根据一组文件创建而来的。该存档工具运行一个MapReduce作业来并行处理所有的输入文件,因此你需要一个MapReduce集群来运行和使用它。这里,HDFS中有一些文档我们希望对它们进行存档:
% hadoop fs -lsr /my/files -rw-r--r-- 1 tom supergroup 1 2009-04-09 19:13 /my/files/a drwxr-xr-x - tom supergroup 0 2009-04-09 19:13 /my/files/dir -rw-r--r-- 1 tom supergroup 1 2009-04-09 19:13 /my/files/dir/b
现在我们可以运行archive指令:
% hadoop archive -archiveName files.har /my/files /my
第一个选项是存档文件的名称,这里是file.har。HAR文件总是一个以.har为扩展名的文件,这是必需的,具体理由见后文描述。接下来的参数是需要存档的文件。 这里我们只存档一棵源文件树下的文件,即HDFS下my/files中的文件,但事实上该工具可以接受多棵源文件树。最后一个参数是HAR文件的输出目录。让我们看看这个存档文件是怎么创建的:
% hadoop fs -ls /my Found 2 items drwxn-xr-x - tom supergroup 0 2009-04-09 19:13 /my/files dnwxn-xr-x - tom supergroup 0 2009-04-09 19:13 /my/files.har % hadoop fs -ls /my/files.har Found 3 items -nw-n--n-- 10 tom supergroup 165 2009-04-09 19:13 /my/files.har/_index -rw-n--r-- 10 tom supergroup 23 2009-04-09 19:13 /my/files.han/_mastenindex -pw-r--p-- 1 tom supergroup 2 2009-04-09 19:13 /my/files.har/part-0
这个目录列表显示了HAR文件的组成部分:两个索引文件以及部分文件的集合———本例中只有一个。这些部分文件中包含已经链接在一起的大量原始文件的内容,并且我们通过索引可以找到包含在存档文件中的部分文件,它的起始点和长度。但所有这些细节对于使用har URI方案与HAR文件交互的应用都是隐式的,并且HAR文件系统是建立在基础文件系统上的(本例中是HDFS)。以下命令以递归方式列出了存档文件中的部分文件:
% hadoop fs -lsr har:///my/files.har drw-r--r-- - tom supergroup 0 2009-04-09 19:13 /my/files.har/my drw-r--r-- - tom supergroup 0 2009-04-09 19:13 my/files.har/my/files -rw-r--r-- 10 tom supergroup 1 2009-04-09 19:13 /my/files.har/my/files/a drw-r--r-- - tom supergroup 0 2009-04-09 19:13 /my/files.han/my/files/din -rw-n--n-- 10 tom supergroup 1 2009-04-09 19:13 /my/files.han/my/files/dir/b
如果HAR文件所在的文件系统是默认的文件系统,这就非常直观易懂。另一方面,如果你想在其他文件系统中引用HAR文件,则需要使用一个不同于正常情况下的URI路径格式。以下两个指令作用相同,例如:
% hadoop fs -lsr har:///my/files.har/my/files/dir % hadoop fs -lsr har://hdfs-localhost:8020/my/files.har/my/files/dir
注意第二个格式,仍以har方案表示一个HAR文件系统,但是由hdfs指定基础文件系统方案的权限,后面加上一个斜杠和HDFS主机(localhost)及端口(8020)。我们现在可以知道为什么HAR文件必须要有.har扩展名。通过查看权限和路径及.har扩展名的组成,HAR文件系统将har URI转换成为一个基础文件系统的URI。 在本例中是hdfs://localhost:8020/user/tom/files.har。路径的剩余部分是文件在存档 文件系统中的路径:/user/tom/files/dir。
要想删除HAR文件,需要使用递归格式进行删除,因为对于基础文件系统来说, HAR文件是一个目录:
%hadoop fs -rmr /my/files.har
不足
对于HAR文件,还需要了解一些它的不足。创建一个存档文件会创建原始文件的一个复本,因此你至少需要与要存档(尽管创建了存档文件后可以删除原始文件)的文件容量相同大小的磁盘空间。虽然存档文件中源文件能被压缩(HAR 文件在这方面更接近于tar文件),但目前还不支持存档文件的压缩。
一旦创建,存档文件便不能再修改。要想从中增加或删除文件,必须重新创建存档文件。事实上,一般不会再对存档后的文件进行修改,因为它们是定期成批存档的,比如每日或每周。
如前所述,HAR文件可以作为MapReduce的输入。然而,InpuFormat类并不知道文件已经存档,尽管该类可以将多个文件打包成一个MapReduce分片,所以即使在HAR文件中处理许多小文件,也仍然低效的。