我有一个RDD包含一些对象的计数,然后我对它应用reduceByKey(),总结所有元素(比如单词计数示例)。我已将reduceByKey转换的输出保存到文本文件中,并为每个工作人员提供了总和:
(work at LEFT null,9741)
(work at LEFT null,10073)
(work at LEFT null,10348)
(work at LEFT null,10483)
(work at LEFT null,10754)
它不应该只是一个项目,它们都是它们的总和吗?
如果需要更多细节,我会提供。
LE:我想要计算的对象由
定义public class Pattern {
string pattern;
PatternType type;
Relation r;
}
答案 0 :(得分:2)
在Spark中,PairRDDFunctions.reduceByKey
使用RDD[(K, V)]
并使用定义的分区器对数据进行分区(导致混乱)。如果未提供此类分区程序,则使用默认的HashPartitioner
来确定将哪个键值对传递给哪个工作程序。如果您使用Java类作为没有覆盖它的hashCode
方法的密钥,reduceByKey
将决定如何基于Java'来对数据进行分区。 s Object.hashCode
。这意味着相同的密钥将被卸载到不同的工作人员,在那里他们将被部分地缩小在一起。理想情况下,这不是你想要的。你想要的是具有相同键的所有对象将通过同一个工作者减少。然后,当每个工作人员减少它们自己后,它们将被洗牌,所有键的组合器都无法根据其哈希码匹配键,这解释了为什么你只能看到它们部分减少数据而不是单个密钥上的汇总数据。
您需要做的是提供正确的hashCode
和 equals
实施。这在Spark documentation中说明(感谢@VitaliyKotlyarenko):
注意:使用自定义对象作为键值对操作中的键时,必须确保自定义equals()方法附带匹配的hashCode()方法。有关完整的详细信息,请参阅Object.hashCode()文档中概述的合同
例如:
public class Pattern {
string pattern;
PatternType type;
Relation r;
@Override
public int hashCode() {
return 371 * pattern.hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (other == null || this.getClass() != other.getClass()) return false;
Pattern pattern = (Pattern) other;
return this.pattern.equals(pattern.pattern);
}
}