我正在处理hadoop中的输入日志文件,其中密钥不均匀分布。这意味着减速器的值分布不均匀。例如,key1有1个值,key2有1000个值。
有没有办法对与同一个键相关联的值进行负载平衡[我也不想修改我的密钥]
答案 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);
}
}
}