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

Java 我应该将变量保留为瞬态变量吗?,java,serialization,apache-spark,transient,Java,Serialization,Apache Spark,Transient,我一直在尝试使用ApacheSpark来解决一些查询,如top-k、skyline等 我制作了一个包装器,其中包含SparkConf和JavaSparkContext名为SparkContext。该类还实现了可序列化,但由于SparkConf和JavaSparkContext不可序列化,因此该类也不可序列化 我有一个名为topK的类来解决topK查询,该类实现了serializable,但该类还有一个SparkContext成员变量,该变量不可序列化(出于上述原因)。因此,每当我试图从RDD中的

我一直在尝试使用ApacheSpark来解决一些查询,如top-k、skyline等

我制作了一个包装器,其中包含
SparkConf
JavaSparkContext
名为
SparkContext
。该类还实现了可序列化,但由于
SparkConf
JavaSparkContext
不可序列化,因此该类也不可序列化

我有一个名为
topK
的类来解决topK查询,该类实现了serializable,但该类还有一个
SparkContext
成员变量,该变量不可序列化(出于上述原因)。因此,每当我试图从RDD中的
.reduce()
函数中执行
TopK
方法时,就会出现异常

我找到的解决方案是使
SparkContext
transient

我的问题是:我应该将
SparkContext
变量保持为瞬态变量,还是犯了一个大错误

SparkContext
class:

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);
    }

}
public class TopK implements QueryCalculator, Serializable {

    private final transient SparkContext sparkContext;
    .
    .
    .
}
抛出任务不可序列化的
异常的示例。
getBiggestPointByXDimension
甚至不会被输入,因为为了在reduce函数中执行它,包含它的类(
TopK
)必须是可序列化的

private Point findMedianPoint(JavaRDD<Point> points) {
    Point biggestPointByXDimension = points.reduce((a, b) -> getBiggestPointByXDimension(a, b));
    .
    .
    .
}

private Point getBiggestPointByXDimension(Point first, Point second) {
        return first.getX() > second.getX() ? first : second;
    }
专用点findMedianPoint(JavaRDD点){
Point biggestPointByXDimension=点。减少((a,b)->getBiggestPointByXDimension(a,b));
.
.
.
}
私有点getBiggestPointByXDimension(第一点,第二点){
返回first.getX()>second.getX()?first:second;
}
对于您的问题:我应该将SparkContext变量保持为瞬态吗

对。没关系。它只封装(Java)SparkContext,上下文在Worker上不可用,因此将其标记为transient只会告诉序列化程序不要序列化该字段

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


还有一件事:正如您所指出的,Spark之所以尝试序列化完整的封闭类,是因为该类的一个方法正在闭包中使用。避免那样!。使用匿名类或自包含闭包(最终将转换为匿名类)。

为什么TopK需要序列化?@ChristianStrempfer我在帖子中添加了一个示例。问题是我不能在
reduce()
函数中执行函数,除非函数所源自的类是可序列化的。所以你是说我应该有一个单独的类(比如
TopKProcessor
),它将封装我想要对RDD执行的每个操作(比如
reduce())
reduceByKey()
等)?不,我是说,你可以在闭包中声明那些简单的操作,比如:
points.reduce((a,b)->a.getX()>b.getX(),
你可以在闭包中声明这些操作:
points.reduce((a,b)->a.getX()>b.getX()?a:b)
避免调用在类上定义的方法。我同意你的观点,我可能会这样做,但也有其他情况,计算逻辑太大,会导致嵌套混乱。但我会尽我最大的努力避免这种情况。或者向你学习一些Scala-Scala和Spark是一个很好的组合。我已经看到Scala是如何在Spark中使用的,我发现它非常简单,可能比Java更好(对于这样的任务),但我正在与我的一位教授合作,我们同意使用Java。虽然我很确定我将来会学习一些Scala,因为我喜欢它。