我一直在尝试使用Apache Spark尝试解决一些查询,例如top-k,skyline等。
我制作了一个包装SparkConf
和JavaSparkContext
名为SparkContext
的包装器。此类还实现了可序列化,但由于SparkConf
和JavaSparkContext
不可序列化,因此该类也不是。
我有一个类解决名为TopK
的topK查询,该类实现了serializable,但该类还有一个SparkContext
成员变量,该变量不可序列化(由于上述原因)。因此,每当我尝试在RDD中的TopK
函数内执行.reduce()
方法时,我都会收到异常。
我找到的解决办法是SparkContext
瞬态。
我的问题是:我应该将SparkContext
变量保留为瞬态还是我犯了一个大错误?
SparkContext
课程:
import java.io.Serializable;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.*;
public class SparkContext implements Serializable {
private final SparkConf sparConf; // this is not serializable
private final JavaSparkContext sparkContext; // this is not either
protected SparkContext(String appName, String master) {
this.sparConf = new SparkConf();
this.sparConf.setAppName(appName);
this.sparConf.setMaster(master);
this.sparkContext = new JavaSparkContext(sparConf);
}
protected JavaRDD<String> textFile(String path) {
return sparkContext.textFile(path);
}
}
TopK
课程:
public class TopK implements QueryCalculator, Serializable {
private final transient SparkContext sparkContext;
.
.
.
}
抛出Task not serializable
异常的示例。 getBiggestPointByXDimension
甚至都不会被输入,因为为了在reduce函数中执行它,将它封闭的类({{ 1}})必须是可序列化的。
TopK
答案 0 :(得分:5)
问题:我应该将SparkContext变量保留为瞬态吗?
是。没关系。它只封装了(Java)SparkContext,并且上下文在worker上不可用,因此标记它transient
只是告诉Serializer不要序列化该字段。
您也可以让自己的SparkContext
包装器不可序列化,并将其标记为瞬态 - 与上述效果相同。 (顺便说一句,鉴于SparkContext是Spark上下文的Scala类名,我选择了另一个名称以避免混乱)。
还有一件事:正如你所指出的,Spark试图序列化完整的封闭类的原因是因为在闭包中使用了类的方法。避免这样!使用匿名类或自包含的闭包(最后将转换为匿名类)。