处理Hadoop mapreduce中各键之间值的不均匀分布

时间:2013-07-25 23:49:30

标签: java hadoop mapreduce partitioning hadoop-partitioning

我正在处理hadoop中的输入日志文件,其中密钥不均匀分布。这意味着减速器的值分布不均匀。例如,key1有1个值,key2有1000个值。

有没有办法对与同一个键相关联的值进行负载平衡[我也不想修改我的密钥]

2 个答案:

答案 0 :(得分:0)

如果你知道哪些键会有非常大的值,你可以使用以下技巧。

您可以实现一个自定义Partitioner,它可以确保每个偏斜的密钥都转到一个分区,然后其他所有内容都会被hashCode分配给剩余的分区(这就是默认HashPartitioner确实如此。

您可以通过实现此界面来创建自定义Partitioner

public interface Partitioner<K, V> extends JobConfigurable {
  int getPartition(K key, V value, int numPartitions);
}

然后你可以告诉Hadoop使用你的Partitioner

conf.setPartitionerClass(CustomPartitioner.class);

答案 1 :(得分:0)

也许你可以在击中减速器前使用合成器?这是相当推测的......

想法是将每组密钥划分为预设最大大小的分区,然后将这些分区的k / v对输出到reducer。此代码假定您已在配置中的某个位置设置该大小。

public static class myCombiner extends Reducer<Text, Text, Text, Text> {
    public void reduce(Text key, Iterable<Text> values, Context context)
            throws IOException, InterruptedException {

        List<Text> textList = new ArrayList<Text>();
        int part = 0;

        while (values.iterator().hasNext()) {
            if (textList.size() <= Integer.parseInt(context.getConfiguration().get("yourMaxSize"))) {
                textList.add(values.iterator().next());

            } else {
                for(Text t : textList) {
                    //essentially partitioning each key...
                    context.write(new Text(key.toString() + "_" + Integer.toString(part)), t);
                }
                textList.clear();
            }
            part += 1;
        }
        //output any stragglers ... 
        for(Text t : textList) {
            context.write(new Text(key.toString() + "_" + Integer.toString(part)), t);
        }

    }
}