Обработка полностью изменяемых имен перезаписываемых имен в Hadoop SequenceFile

У меня есть несколько файлов Hadoop SequenceFiles, которые были написаны с помощью некоторого записываемого подкласса, который я написал. Давайте назовем это 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 с твиком, который делает его менее сложным. Если у меня много больших файлов, это все еще довольно непрактично.

Есть ли лучший способ справиться с рефакторингами полностью определенных имен классов, используемых в SequenceFiles? В идеале я ищу какой-то способ указать новое резервное имя класса, если указанное не найдено, чтобы можно было работать как с датированными, так и с обновленными типами этого SequenceFile.

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: Почему рыба была в пакете млекопитающих в первую очередь? ;)

Глядя на спецификацию для sequencefile, становится ясно, что альтернативные имена классов не рассматриваются.

Если бы у меня не было возможности переписать данные, еще одним вариантом было бы иметь com.mammals.fishes.writable extension com.vertebrates.fishes.writable и просто аннотировать его как устаревшее, чтобы никто случайно не добавил код в пустое обертка. По прошествии достаточно длительного времени данные, записанные в старом классе, будут устаревшими, и вы сможете безопасно удалить класс млекопитающих.

Другие вопросы по тегам