根据自定义分区程序的“getPartition”方法的输出,我遇到的问题是自定义中间键没有在我想要的分区中结束。我可以在我的映射器日志文件中看到分区器生成了预期的分区号,但是有时带有公共分区号的键不会在同一个reducer中结束。
具有共同“getPartition”输出的键如何以不同的reducers结束?
在所有“getPartition”调用完成后,我在mapper日志文件中注意到,对自定义中间键“hashCode”和“compareTo”方法进行了多次调用。映射器是否只是在分区排序中进行,还是这可能是问题的一部分?
我附加了自定义中介密钥和分区程序的代码。注意:我知道确切的1/2键将“useBothGUIDFlag”设置为true,而1/2将此设置为false(这就是为什么我将这些键分区为分隔空间的不同部分)。我也知道密钥似乎没有跨越到分区的另一半(即,“useBothGUIDFlag”键不会在“!useBothGUIDFlag”分区中结束,反之亦然),而是它们在其一半内混淆分区。
public class IntermediaryKey implements WritableComparable<IntermediaryKey> {
public String guid1;
public String guid2;
public boolean useBothGUIDFlag;
@Override
public int compareTo(IntermediaryKey other) {
if(useBothGUIDFlag)
{
if(other.useBothGUIDFlag)
{
return this.hashCode() - other.hashCode();
}else{
return 1;
}
}else{
if(!other.useBothGUIDFlag)
{
return guid2.compareTo(other.guid2);
}else{
return -1;
}
}
}
@Override
public int hashCode()
{
if(useBothGUIDFlag)
{
if(guid1.compareTo(guid2) > 0)
{
return (guid2+guid1).hashCode();
}else{
return (guid1+guid2).hashCode();
}
}else{
return guid2.hashCode();
}
}
@Override
public boolean equals(Object otherKey)
{
if(otherKey instanceof IntermediaryKey)
{
return this.compareTo((IntermediaryKey)otherKey) == 0;
}
return false;
}
}
public static class KeyPartitioner extends Partitioner<IntermediaryKey, PathValue>
{
@Override
public int getPartition(IntermediaryKey key, PathValue value, int numReduceTasks) {
int bothGUIDReducers = numReduceTasks/2;
if(bothGUIDReducers == 0)
{
return 0;
}
int keyHashCode = Math.abs(key.hashCode());
if(key.useBothGUIDFlag)
{
return keyHashCode % bothGUIDReducers;
}else{
return (bothGUIDReducers + (keyHashCode % (numReduceTasks-bothGUIDReducers)));
}
}
}
答案 0 :(得分:0)
问题最终出现在自定义密钥(IntermediaryKey)的序列化/反序列化中。正在阅读“useBothGUIDFlag”变量,与其本应相反。
在reducer中获取“mapred.task.partition”属性值有助于注意到已发生此交换。具有相反“useBothGUIDFlag”值的键似乎将转到正确的reducer。