我应该将变量保留为瞬态变量吗?

时间:2014-11-22 12:13:37

标签: java serialization apache-spark transient

我一直在尝试使用Apache Spark尝试解决一些查询,例如top-k,skyline等。

我制作了一个包装SparkConfJavaSparkContext名为SparkContext的包装器。此类还实现了可序列化,但由于SparkConfJavaSparkContext不可序列化,因此该类也不是。

我有一个类解决名为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

1 个答案:

答案 0 :(得分:5)

问题:我应该将SparkContext变量保留为瞬态吗?

是。没关系。它只封装了(Java)SparkContext,并且上下文在worker上不可用,因此标记它transient只是告诉Serializer不要序列化该字段。

您也可以让自己的SparkContext包装器不可序列化,并将其标记为瞬态 - 与上述效果相同。 (顺便说一句,鉴于SparkContext是Spark上下文的Scala类名,我选择了另一个名称以避免混乱)。

还有一件事:正如你所指出的,Spark试图序列化完整的封闭类的原因是因为在闭包中使用了类的方法。避免这样!使用匿名类或自包含的闭包(最后将转换为匿名类)。