当前位置: 首页 > 知识库问答 >
问题:

理解Spark序列化

陈俊誉
2023-03-14

在Spark中,如何知道哪些对象在driver上实例化,哪些对象在executor上实例化,因此如何确定哪些类需要实现Serializable?

共有1个答案

冷英光
2023-03-14

序列化对象意味着将其状态转换为字节流,以便字节流可以恢复为对象的副本。如果Java对象的类或其任何超类实现Java.io.serializable接口或子接口Java.io.Externalizable,则该对象是可序列化的。

类从不序列化,只有类的对象才序列化。如果对象需要持久化或通过网络传输,则需要对象序列化。

Class Component            Serialization
instance variable           yes
Static instance variable    no
methods                     no
Static methods              no
Static inner class          no
local variables             no

让我们以一个示例Spark代码并经历各种场景

public class SparkSample {

      public int instanceVariable                =10 ;
      public static int staticInstanceVariable   =20 ;

      public int run(){

         int localVariable                       =30;

         // create Spark conf
         final SparkConf sparkConf = new SparkConf().setAppName(config.get(JOB_NAME).set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");

         // create spark context 
         final JavaSparkContext sparkContext = new JavaSparkContext(sparkConf);

        // read DATA 
        JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD(); 


        // Anonymous class used for lambda implementation
        JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
                @Override
                public Iterator<String> call(String s) {
                // How will the listed varibles be accessed in RDD across driver and Executors 
                System.out.println("Output :" + instanceVariable + " " + staticInstanceVariable + " " + localVariable);
                return Arrays.asList(SPACE.split(s)).iterator();
        });

        // SAVE OUTPUT
        words.saveAsTextFile(OUTPUT_PATH));

      }

       // Inner Static class for the funactional interface which can replace the lambda implementation above 
       public static class MapClass extends FlatMapFunction<String, String>() {
                @Override
                public Iterator<String> call(String s) {
                System.out.println("Output :" + instanceVariable + " " + staticInstanceVariable + " " + localVariable);
                return Arrays.asList(SPACE.split(s)).iterator();
        }); 

        public static void main(String[] args) throws Exception {
            JavaWordCount count = new JavaWordCount();
            count.run();
        }
}
    Inner class        | Instance Variable (Outer class) | Static Instance Variable (Outer class) | Local Variable (Outer class)

    Anonymous class    | Accessible And Serialized       | Accessible yet not Serialized          | Accessible And Serialized 

    Inner Static class | Not Accessible                  | Accessible yet not Serialized          | Not Accessible 

如果在内部类中访问了任何外部类实例变量,编译器会应用不同的逻辑来访问它们,因此外部类是否被序列化取决于您访问的是什么。

就Java而言,整个争论都是关于外部类与内部类以及访问外部类引用和变量如何导致序列化问题的。

各种方案:

anonymo-class(){

 final Outer-class reference;

 Anonymous-class( Outer-class outer-reference){

reference = outer-reference;

}

}

外部类被序列化并与内部匿名类的序列化对象一起发送

引用外部类对象和局部变量refrence的匿名类。

外部类对象用于访问实例变量

anonymo-class(){

 final Outer-class reference;

final Local-variable localRefrence ;

 Anonymous-class( Outer-class outer-reference, Local-variable localRefrence){

reference = outer-reference;

this.localRefrence = localRefrence;

}

无法访问

无法访问

由于静态变量没有序列化,因此没有外部类对象被序列化。

>

  • 遵循Java序列化规则来选择需要序列化的类对象。

    使用javap-p-c“abc.class”打开字节码,查看编译器生成的代码

    根据您试图在外部类的内部类中访问的内容,编译器生成不同的字节代码。

    任何声明为瞬态的实例变量都不会在驱动程序上序列化。

  •  类似资料:
    • 免责声明:刚刚开始和斯巴克玩。 我很难理解著名的“任务不可序列化”异常,但我的问题与我在SO上看到的问题有点不同(或者我认为是这样)。 我有一个很小的自定义RDD()。它有一个字段,用于存储类不实现序列化的对象()。我已经设置了spark.serializer配置选项来使用Kryo。但是,当我在我的RDD上尝试时,我得到了以下结果: 当我往里面看的时候。submitMissingTasks我看到它

    • 本文向大家介绍详解PHP序列化和反序列化原理,包括了详解PHP序列化和反序列化原理的使用技巧和注意事项,需要的朋友参考一下 0.前言 对象的序列化和反序列化作用就不再赘述,php中序列化的结果是一个php自定义的字符串格式,有点类似json. 我们在任何语言中设计对象的序列化和反序列化都需要解决几个问题 把某个对象序列化之后,序列化的结果有自描述的功能(从序列化的结果中知道这个对象的具体类型, 知

    • 我在程序中使用,需要序列化内核以便以后重用它们。 为此,我使用: 如何定义必须使用?

    • 在流中,对任何对象的第一个引用会导致对象被序列化或外部化,并为该对象分配句柄。对该对象的后续引用被编码为句柄。使用对象句柄可以保留对象图中自然出现的共享和循环引用。对对象的后续引用仅使用句柄,从而允许非常紧凑的表示形式。 除可序列化字段外,基本数据以块数据记录的形式写入流,每条记录都以标记和记录中字节数的指示作为前缀。 以上内容来自Oracle Docs for Serialization。我正在

    • 问题内容: 我正在尝试从Spark中的java.time.format使用DateTimeFormatter,但它似乎不可序列化。这是相关的代码块: 如何避免出现异常?是否有更好的库来解析时间戳?我读过,Joda也不是可序列化的,并且已并入Java 8的时间库中。 问题答案: 您可以通过两种方式避免序列化: 假设其值可以是恒定的,请将格式化程序放在中(使其成为“静态”)。这意味着可以在每个工作程序

    • 我对Spark,Scala和Cassandra都是新手。使用Spark,我试图从MySQL获取一些ID。 我可以看到在控制台打印的ID。 当我试图在每个提取id上运行相同的函数时 它给出与例外相同的例外 在阅读spark-shell中的Apache spark:“sparkException:Task not serializable”后,我尝试将@transient添加到RDDs中