Hadoop: как выводить разные типы форматов в одном задании?

Я хочу выводить форматы gzip и lzo одновременно в одном задании.

Я использовал MultipleOutputs и добавил два именованных выхода, например:

MultipleOutputs.addNamedOutput(job, "LzoOutput", GBKTextOutputFormat.class, Text.class, Text.class);

GBKTextOutputFormat.setOutputCompressorClass(job, LzoCodec.class);

MultipleOutputs.addNamedOutput(job, "GzOutput", TextOutputFormat.class, Text.class, Text.class);

TextOutputFormat.setOutputCompressorClass(job, GzipCodec.class);

(GBKTextOutputFormat здесь написано мной, что расширяет FileOutputFormat)

Они используются в редукторе, например:

multipleOutputs.write("LzoOutput", NullWritable.get(), value, "/user/hadoop/lzo/"+key.toString());

multipleOutputs.write("GzOutput", NullWritable.get(), value, "/user/hadoop/gzip/"+key.toString());

Результат:

Я могу получить выходные данные по двум путям, но они оба в формате gzip.

Кто-нибудь может мне помочь? Спасибо!

==========================================================================

Более:

Я только что посмотрел исходный код setOutputCompressorClass в FileOutputFormat, в котором conf.setClass("mapred.output.compression.codec", codecClass, CompressionCodec.class);

Кажется, что mapred.output.compression.codec в конфигурации будет сброшен при вызове setOutputCompressorClass.

Таким образом, фактический формат сжатия — это тот, который мы установили в конце, и мы не можем установить два разных формата сжатия в одном и том же задании? Или что-то еще игнорируется?


person thomaslee    schedule 18.10.2012    source источник
comment
Подтвердили ли вы, что ваш GBKTextOutputFormat работает при использовании в качестве единственного типа выходного формата в редюсере, который не использует MultipleOutput? Кроме того, что в вашем пользовательском классе формата вывода класс сжатия установлен на что-то отличное от GzipCodec в методе getRecordWriter()?   -  person Chris Gerken    schedule 19.10.2012
comment
Я имел в виду класс сжатия по умолчанию...   -  person Chris Gerken    schedule 19.10.2012


Ответы (1)


Поэтому, возможно, в качестве обходного пути попробуйте установить правильный outputCompressorClass непосредственно в конфигурации.

context.getConfiguration().setOutputCompressorClass(GzipCodec.class);

непосредственно перед вашим вызовом записи на каждый из выходов. Похоже, что любые параметры конфигурации формата вывода, кроме класса ключа, класса значения и пути вывода, не обрабатываются MultipleOutputs должным образом, и нам, возможно, придется написать немного кода, чтобы компенсировать это упущение.

person Chris Gerken    schedule 18.10.2012
comment
Спасибо за ответ! GBKTextOutputFormat на самом деле хорошо работает, когда есть только один тип выходного формата. Я попытаюсь установитьOutputCompressorClass перед каждым multipleOutputs.write(...). - person thomaslee; 19.10.2012
comment
Я с нетерпением жду, чтобы услышать, как это идет. Объект MultipleOutputs, который вы создаете, фактически кэширует RecordWriter для каждого вывода, и этот RecordWriter создается при первой попытке записать что-либо в вывод. Проблема, которую мы уже обсуждали, заключается в том, что разные выходные данные накладываются друг на друга в настройках конфигурации, и тогда записи записи создаются неправильно. Теоретически :) - person Chris Gerken; 19.10.2012
comment
RecordWriter кэшируется в объекте MultipleOutputs точно так же, как и ваша точка. Контекст RecordWriter получается с помощью taskContext = getContext(...);, которые напрямую возвращают taskContext, если он не равен нулю. Из-за этого наш setOutputCompressorClass перед MultipleOutputs.write не работает. Поэтому я копирую MultipleOutputs как другой класс и изменяю функцию getContext(). Он не вернется, если taskContext != null. Кажется, теперь все в порядке, и что я должен сделать дальше, так это убедиться, что экземпляр taskContext создается только один раз для каждого nameOutput, иначе он будет работать слишком медленно. Спасибо большое!!! - person thomaslee; 19.10.2012
comment
Я не думал о создании нового класса, подобного MultipleOutputs. Очень круто. - person Chris Gerken; 19.10.2012
comment
@thomaslee: см. мой ответ на этот вопрос: stackoverflow.com/questions/12981233/ - person Chris Gerken; 23.10.2012
comment
Хороший! Это помогает мне выводить в разные каталоги, которые неизвестны заранее. Спасибо! @Крис - person thomaslee; 23.10.2012