当Tuple2的键是mapToPair

时间:2017-02-25 06:20:12

标签: apache-spark mapreduce spark-streaming

我在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

  1. 当sourceDStream的大小很小(比如50或更小)时,Spark不会调用SourceObject的等号,因此依次不会调用reduceByKey。 因此,调用foreachPartition时不会缩减/合并重复键。

  2. 即使sourceDStream的大小比100+更大,Spark也只调用SourceObject的一小部分对象, 即使sourceDStream中有更多对象具有相同的键。因此,对于具有相同键的剩余许多对象,不会调用reduceByKey。

  3. 上述两种情况都会导致过多的对象具有与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中的所有对象相等,以便减少具有相同键的对象?

    感谢。

    迈克尔,

0 个答案:

没有答案