我们正在尝试为RDD分配相同的执行程序和相同的分区程序以避免任何网络流量,并且像cogroup和join这样的shuffle操作没有任何阶段边界,并且所有转换都在一个阶段完成。
为了实现这一点,我们使用Java中的自定义RDD类(ExtendRDD.class)包装RDD,该类具有来自RDD.class(在scala中)的覆盖getPreferredLocation函数:
public Seq<String> getPreferredLocations(Partition split){
listString.add("11.113.57.142");
listString.add("11.113.57.163");
listString.add("11.113.57.150");
List<String> finalList = new ArrayList<String>();
finalList.add(listString.get(split.index() % listString.size()));
Seq<String> toReturnListString = scala.collection.JavaConversions.asScalaBuffer(finalList).toSeq();
return toReturnListString;
}
有了这个,我们就可以控制spark的行为,看看它将RDD放在集群中的哪个节点。但现在的问题是,自分区器以来 对于这些RDD不同,spark认为它们与shuffle相关,并再次为这些shuffle操作创建多个阶段。我们尝试在同一个自定义RDD中覆盖相同RDD.class的分区方法:
public Option<Partitioner> partitioner() {
Option<Partitioner> optionPartitioner = new Some<Partitioner>(this.getPartitioner());
return optionPartitioner;
}
对于将它们放在同一阶段的火花,必须考虑这些RDD来自同一个分区。 我们的分区方法似乎不起作用,因为spark为2个RDD提供了不同的分区,并为shuffle操作创建了多个阶段。
我们使用自定义RDD将scala RDD包装为:
ClassTag<String> tag = scala.reflect.ClassTag$.MODULE$.apply(String.class);
RDD<String> distFile1 = jsc.textFile("SomePath/data.txt",1);
ExtendRDD<String> extendRDD = new ExtendRDD<String>(distFile1, tag);
我们以类似的方式创建另一个自定义RDD,并从该RDD中获取PairRDD(pairRDD2)。然后我们尝试使用partitionBy函数将与extendRDD对象相同的分区器应用于PairRDDFunction对象,然后将cogroup应用于:
RDD<Tuple2<String, String>> pairRDD = extendRDD.keyBy(new KeyByImpl());
PairRDDFunctions<String, String> pair = new PairRDDFunctions<String, String>(pairRDD, tag, tag, null);
pair.partitionBy(extendRDD2.getPartitioner());
pair.cogroup(pairRDD2);
所有这些似乎都不起作用,因为当遇到cogroup转换时,spark会产生多个阶段。
有关如何将相同的分区程序应用于RDD的任何建议?