我正在将应用程序从Spark 1.6.2升级到Spark 2.0.2。这个问题与Spark无关。 Spark 1.6.2包括Kryo 2.21。 Spark 2.0.2包含Kryo 3.0.3。
应用程序将一些用Kryo序列化的数据存储在HDFS上。为了节省空间,强制执行Kryo注册。当一个类在Kryo中注册时,它会获得一个顺序ID,这个ID用于表示有线格式的类而不是完整的类名。当我们注册一个新类时,我们总是把它放在最后,所以它得到一个未使用的ID。我们也从不删除注册类。 (如果删除了一个类,我们会在其位置注册一个占位符来保留ID。)这样,ID就可以稳定,一个版本的应用程序可以读取先前版本写入的数据。
事实证明,Kryo使用相同的注册机制在其构造函数中注册基本类。在Kryo 2.21中,它注册了9个基本类,因此第一个用户注册的类获得ID 9.但是Kryo 2.22和更高版本注册了10个基本类。 (void
was added.)这意味着用户注册的类从ID 10开始。
升级到Spark 2.0.2后,我们如何仍然加载旧数据?
(如果我们的第一个用户注册的类是一个已弃用的类,那就太棒了。但事实并非如此。它是scala.Tuple2[_, _]
。)
答案 0 :(得分:1)
实际上有Kryo.register(Class type, int id)
方法可用于显式指定ID。 id
参数的评论说:
id:必须为> = 0.较小的ID会更有效地序列化。默认情况下,ID 0-8用于基本类型和
String
,但这些ID可以重新利用。
自2.22以来注释错误:现在默认情况下也使用ID 9。但实际上它可以改变用途!
kryo.register(classOf[Tuple2[_, _]], 9)
正常的顺序注册适用于其他类。只有第一个类才需要显式ID。