2011-10-06 35 views
4

我试着去学习潜水HDFS中存储的文件到分裂和读给不同的过程(在不同的机器。)的Hadoop在同样大小分割文件

我想到的是,如果我有一个包含1200条记录与SequenceFile 12过程中,我会看到每个过程大约有100条记录。划分文件的方式是获取数据长度,然后除以进程数,为每个分割导出chunk/beg/end大小,然后将该分割通过例如SequenceFileRecordReader,在简单的while循环中检索记录:代码如下。

private InputSplit getSplit(int id) throws IOException { 
... 
    for(FileStatus file: status) { 
     long len = file.getLen(); 
     BlockLocation[] locations = 
      fs.getFileBlockLocations(file, 0, len); 
     if (0 < len) { 
      long chunk = len/n; 
      long beg = (id*chunk)+(long)1; 
      long end = (id)*chunk; 
      if(n == (id+1)) end = len; 
      return new FileSplit(file, beg, end, locations[locations.length-1].getHosts()); 
     } 
    } 
... 
} 

但是,结果显示每个进程统计的总记录总数与存储在文件中的记录不同。将SequenceFile均匀分成块并将它们分发到不同主机的正确方法是什么?

谢谢。

回答

4

我不禁想知道你为什么试图做这样的事情。 Hadoop自动将您的文件和1200条记录拆分为100条记录,听起来不像很多数据。如果你详细说明你的问题,有人可能会更直接地帮助你。

这里是我的两个想法:


选项1:使用Hadoop的自动拆分行为

的Hadoop将自动把您的文件。文件分割成的块的数量是文件的总大小除以块大小。默认情况下,一个地图任务将被分配给每个块(不是每个文件)。

在您的conf/hdfs-site.xml配置文件中,有一个dfs.block.size参数。大多数人将其设置为64或128mb。然而,如果你想要做一些小事情,比如每个块有100个序列文件记录,你可以把它设置得非常低......说1000个字节。我从来没有听说过任何人想要这样做,但它是一种选择。


选项2:使用MapReduce作业来拆分数据。

有你的工作使用“身份映射器”(基本上实现映射器,不要覆盖map)。此外,你的工作使用“身份缩减器”(基本上实施减速器,不要覆盖reduce)。将缩减器的数量设置为您想要的分割数。假设你有三个序列文件要分成25个文件,你需要加载这3个文件,并将reducer的数量设置为25.记录将随机发送给每个reducer,最终结果会接近25次平分。

这是有效的,因为身份映射器和reducer实际上不会做任何事情,所以您的记录将保持不变。记录被发送到随机减速器,然后它们将被写出,每个减速器一个文件到part-r-xxxx文件中。这些文件中的每一个都将包含你的序列文件,甚至可以将它们分成几块。

相关问题