我在JavaDStream sourceDStream中有一个JavaDStream用于流处理。
在这个DStream的mapToPair中,我使用输入对象作为Tuple2的键和值,如
案例1:
public Tuple2<SourceObject, SourceObject> call(SourceObject sourceObject)
Tuple2<WidgetDetail, WidgetDetail> tuple2;
tuple2 = new Tuple2<> (sourceObject, sourceObject);
return tuple2;
}
其中sourceObject也实现了equals(),因为它也被用作mapToPair和reduceByKey中的键。
我还在sourceDStream和rdd上调用缓存,以确保在reduceByKey之前处理它们,如
sourceDStream = sourceDStream.cache ();
rdd = sourceDStream.mapToPair ()
rdd = rdd.cache ();
reducedRdd = rdd.reduceByKey ();
reducedRdd.foreachRDD ();
reducedRdd.foreachPartition ();
然而,Spark
当sourceDStream的大小很小(比如50或更小)时,Spark不会调用SourceObject的等号,因此依次不会调用reduceByKey。 因此,调用foreachPartition时不会缩减/合并重复键。
即使sourceDStream的大小比100+更大,Spark也只调用SourceObject的一小部分对象, 即使sourceDStream中有更多对象具有相同的键。因此,对于具有相同键的剩余许多对象,不会调用reduceByKey。
上述两种情况都会导致过多的对象具有与foreachPartition需要处理的密钥相同的密钥。
然而,当我使用包装器对象作为sourceObject的键时,如下面的代码
案例2:
public class SourceKey {
private SourceObject sourceObject;
public void setSourceObject (SourceObject sourceObject) {
this.sourceObject = sourceObject;
}
public boolean equals (Object obj) {
...
}
}
public Tuple2<SourceKey, SourceKey> call(SourceObject sourceObject)
Tuple2<WidgetDetail, WidgetDetail> tuple2;
SourceKey sourceKey = new SourceKey ();
sourceKey.setSourceObject(sourceObject);
tuple2 = new Tuple2<> (sourceKey, sourceKey);
return tuple2;
}
然后Spark按预期工作,它为SourceDStream中的所有对象调用SourceKey的等于。因此,对具有相同键的所有对象调用reduceByKey。
对于案例1,当SourceObject也被用作mapToPair的Tuple2中的键/值时,为什么Spark会跳过调用SourceObject的等号?
如何解决这个问题并让Spark调用SourceObject对SourceDStream中的所有对象相等,以便减少具有相同键的对象?
感谢。
迈克尔,