我正在编写一个自定义recordReader,它将键值对输出到我的mapper。我真的只需要输出值而不需要键,所以我打算为我的键使用NullWritable,为我的值使用Text。
我基本上使用的是WholeFileInputFormat,如本书中的示例,它也使用了NullWritable键:book link
但是,看看hadoop使用的默认散列分区器,我不知道这怎么会将每条记录发送到同一个映射器:
public class HashPartitioner<K, V> extends Partitioner<K, V> {
public int getPartition(K key, V value, int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
}
由于NullWritable具有相同的hashCode,因此似乎只有一个映射器会处理所有数据。似乎应该有一种方法可以让hadoop均匀地分割所有记录,而不必拿出你自己的密钥。
编辑:为了澄清,我在标准的hadoop格式中谈论 k1 : (k1,v1) - &gt; map(k2,v2) - &gt;结合 - &gt; (k2,v2) - &gt;减少 - &gt; (k3,v3)(输出)
答案 0 :(得分:2)
您作业的映射器数量取决于您从 FileInputFormat 抽象类( InputFormat 接口)覆盖 getSplits 方法的方式。 WholeFileInputFormat 只有一个映射器,因为它在 isSplitable 中返回 false 。 FileInputFormat 中的 getSplits 使用 isSplitable 方法检查输入是否可拆分,并创建分配给Mappers的输入拆分。
您可以查看FileInputFormat中 getSplits 的实施情况,了解详情。
Partitioner没有决定Mapper数量的角色。分区程序的作用是将相同的哈希键发送到同一个Reducer。如果您从Mapper输出 NullWritable 作为键,那么所有键都将转到单个Reducer。
<强>更新强> Mappers的数量基本上不是文件的数量。 HDFS将数据存储到块中。因此,如果HDFS块大小为128MB且文件大小为256MB,那么它可以有两个分割,这些分割将传递给两个不同的Mapper。这就是为什么, isSplitable 进入图片,是否特定文件是可拆分的。
我希望这会有所帮助。