6

私が書いたいくつかの書き込み可能なサブクラスで書かれた一連の Hadoop SequenceFiles があります。それをFishWritableと呼びましょう。

この Writable は、わかりやすくするためにパッケージの名前を変更する必要があると判断するまで、しばらくはうまくいきました。したがって、FishWritable の完全修飾名はcom.vertebrates.fishes.FishWritableではなくcom.mammals.fishes.FishWritable. 問題のパッケージの範囲がどのように進化したかを考えると、これは合理的な変更でした。

次に、SequenceFileRecordReader を初期化しようとするとクラッシュするため、MapReduce ジョブが実行されないことがわかりました。

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)
...

これに対処するためのいくつかのオプションがすぐに明らかになります。以前のすべてのジョブを再実行するだけで、依存するジョブを順番に実行して、最新のキー クラス名で出力を再生成できます。これは明らかに非常に時間がかかり、場合によっては不可能なこともあります。

もう 1 つの可能性は、SequenceFile をテキストとして読み取り、クラス名のインスタンスを新しいものに置き換える単純なジョブを作成することです。これは基本的には方法 1 に微調整を加えたもので、簡単に実行できます。大きなファイルがたくさんある場合、それはまだかなり非現実的です。

SequenceFiles で使用される完全修飾クラス名のリファクタリングを処理するより良い方法はありますか? 理想的には、指定されたクラス名が見つからない場合に新しいフォールバック クラス名を指定して、この SequenceFile の日付付きタイプと更新済みタイプの両方に対して実行できるようにする方法を探しています。

4

2 に答える 2

2

org.apache.hadoop.io.WritableName例外スタック トレースに記載されているクラスには、いくつかの便利なメソッドがあります。

ドキュメントから:

クラス名を含むファイルを無効にすることなく、書き込み可能な実装クラスの名前を変更できるユーティリティ。

// 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 から読み取ろうとすると、新しいcom.vertebrates.fishes.FishWritableクラスが使用されます。

PS: そもそも哺乳類のパッケージに魚が入っていたのはなぜですか? ;)

于 2017-11-08T14:37:44.260 に答える