6

我有一堆 Hadoop 序列文件,它们是用我写的一些 Writable 子类编写的。我们称它为 FishWritable。

这个 Writable 运行了一段时间,直到我决定为了清楚起见需要重命名包。所以现在 FishWritable 的完全限定名称是com.vertebrates.fishes.FishWritable而不是com.mammals.fishes.FishWritable. 鉴于所讨论的一揽子计划的范围是如何演变的,这是一个合理的变化。

然后我发现我的 MapReduce 作业都不会运行,因为它们在尝试初始化 SequenceFileRecordReader 时会崩溃:

java.lang.RuntimeException: java.io.IOException: WritableName can't load class: com.mammals.fishes.FishWritable
at org.apache.hadoop.io.SequenceFile$Reader.getKeyClass(SequenceFile.java:1949)
at org.apache.hadoop.io.SequenceFile$Reader.init(SequenceFile.java:1899)
...

处理此问题的几个选项立即显而易见。我可以简单地重新运行我以前的所有作业,以使用最新的键类名称重新生成输出,按顺序运行任何相关作业。这显然会非常耗时,有时甚至是不可能的。

另一种可能性可能是编写一个简单的作业,将 SequenceFile 作为文本读取,并将类名的任何实例替换为新实例。这基本上是方法#1,稍加调整使其变得不那么复杂。如果我有很多大文件,那仍然是不切实际的。

有没有更好的方法来处理序列文件中使用的完全限定类名的重构?理想情况下,我正在寻找某种方法来指定新的后备类名称(如果找不到指定的类名),以允许针对此 SequenceFile 的过时和更新类型运行。

4

2 回答 2

3

查看 sequencefile 的规范,似乎很明显没有考虑替代类名。

如果我无法重新编写数据,另一种选择是让 com.mammals.fishes.writable 扩展 com.vertebrates.fishes.writable 并将其注释为已弃用,这样就不会有人不小心将代码添加到空包装。足够长的时间后,旧类写入的数据将被废弃,您将能够安全地删除哺乳动物类。

于 2013-12-30T03:50:49.807 回答
2

org.apache.hadoop.io.WritableName异常堆栈跟踪中提到的类有一些有用的方法。

文档

允许重命名 Writable 实现类而不会使包含其类名的文件无效的实用程序。

// Add an alternate name for a class.
public static void addName(Class writableClass, String name)

在您的情况下,您可以在读取您的 SequenceFiles 之前调用它:

WritableName.addName(com.vertebrates.fishes.FishWritable.class, "com.mammals.fishes.FishWritable");

这样,当尝试com.mammals.fishes.FishWritable从旧的 SequenceFile 读取 a 时,com.vertebrates.fishes.FishWritable将使用新的类。

PS:为什么一开始是哺乳动物包里的鱼?;)

于 2017-11-08T14:37:44.260 回答