关于kryo序列化我缺少什么?
Class1和Class3并不是Java可序列化的类(没有默认的构造函数,没有getter和setter)
当我尝试“使用”实例时,该实例是在Spark内部由Spark上下文创建的,无论是否将Classe3注册为Kryo类,我都会遇到序列化问题。
工作正常:
Dataset<Class1> ds = spark.createDataset(classes, Encoders.kryo(Class1.class));
Dataset<String> df = df.map((MapFunction<Class1, String>) class1 -> class1.getName(), Encoders.STRING());
df.show();
由Class3引起的序列化错误
spark = SparkSession
.builder()
.master("local[*]")
.config(new SparkConf().registerKryoClasses(new Class[] {Class3.class}))
.appName("spark_test")
.getOrCreate();
Class3 class3 = Class3.getInstance();
Dataset<Class1> ds = spark.createDataset(classes, Encoders.kryo(Class1.class));
Dataset<String> df = df.map((MapFunction<Class1, String>) class1 -> class1.getName() + "-" class3.getId(), Encoders.STRING());
df.show();
答案 0 :(得分:1)
总结评论中发生的讨论以形成答案-
当您尝试调用转换时,Spark驱动程序将必须为该转换中的代码创建一个闭包并将其交付给负责运行它的执行程序。在您的情况下,代码行Class3 class3 = Class3.getInstance();
是Scala对象的一部分,它封装了Spark上下文的创建和使用以产生某种结果,即驱动程序。因此,当您尝试在地图转换中传递class3
时,驱动程序将尝试序列化封闭的Scala对象。除非您实现可序列化,否则此scala对象本身无法序列化,因此会遇到序列化问题。
Re:Kryo序列化-因为您已经在Kryo中注册了Class3,所以它将帮助您序列化Class3实例,但是不会序列化具有Class3实例作为变量的Composite对象。
因此,如果您提取class3.getId()
的值,然后将其传递给地图转换,则无需在Kryo中注册Class3。
在上面包含我上面提到的Scala对象的示例中,该示例与Driver应用程序相同。
希望这会有所帮助。