2011-11-15 3 views
7

У меня есть файл, в котором набор из каждых четырех строк представляет запись.Hadoop читает несколько строк за раз

например, первые четыре строки представляют record1, следующие четыре представляют собой запись 2 и так далее ..

Как я могу обеспечить ввод Mapper эти четыре строки в то время?

Кроме того, я хочу, чтобы файл расщепления в Hadoop произойдет на границе рекорд (номер строки должен быть кратно четырем), так что записи не получить промежуток между несколькими сплит-файлов ..

Как это может сделать?

ответ

11

Несколько подходов, некоторые грязнее другие:


правильный путь

Вы, возможно, придется определить свой собственный RecordReader, InputSplit и InputFormat. В зависимости от того, что вы пытаетесь сделать, вы сможете повторно использовать некоторые из уже существующих из трех выше. Вероятно, вам придется написать собственный RecordReader для определения пары ключ/значение, и вам, скорее всего, придется написать свой собственный InputSplit, чтобы определить границу.


Другой правильный путь, который не может быть возможным

выше задача является довольно сложной. У вас есть контроль над вашим набором данных? Можете ли вы предварительно обработать его каким-либо образом (либо в то время как он приходит или отдыхает)? Если это так, вы должны серьезно подумать о том, чтобы попытаться преобразовать ваш набор данных в нечто, что легче читать из окна в Hadoop.

Что-то вроде:

ALine1 
ALine2   ALine1;Aline2;Aline3;Aline4 
ALine3 
ALine4  -> 
BLine1 
BLine2   BLine1;Bline2;Bline3;Bline4; 
BLine3 
BLine4 

и грязный

У вас есть контроль над файлами размеров ваших данных? Если вы вручную разделите свои данные на границе блока, вы можете заставить Hadoop не беспокоиться о записях, охватывающих расщепления. Например, если размер вашего блока равен 64 МБ, напишите свои файлы в кусках на 60 МБ.

Не волнуясь о разрыве входных данных, вы можете сделать что-то грязное: в вашей функции карты добавьте новую пару ключ/значение в объект списка. Если в объекте списка есть 4 элемента, выполните обработку, испустите что-то, а затем очистите список. В противном случае, не испускайте ничего и не двигайтесь, не делая ничего.

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

+0

Спасибо за ваш ответ, я думал о втором подходе вы предложили, но не то, что также пронизан с той же проблемой? Как я могу читать четыре строки в момент добавления их вместе и создания одной строки? – Gitmo

+0

Вы могли бы написать что-то в Perl или Python, которые могли бы сделать трюк. Вот что я имел в виду. –

+0

Используйте [SequenceFile] (http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/io/SequenceFile.html) с сжатием для лучшей производительности, если предварительная обработка файла выполнена , –

3

Другой способ (простой, но может быть неэффективен в некоторых случаях) - реализовать FileInputFormat#isSplitable(). Затем входные файлы не разбиваются и обрабатываются по одному на карту.

import org.apache.hadoop.fs.*; 
import org.apache.hadoop.mapred.TextInputFormat; 
public class NonSplittableTextInputFormat extends TextInputFormat { 
    @Override 
    protected boolean isSplitable(FileSystem fs, Path file) { 
     return false; 
    } 
} 

И как orangeoctopus сказал

In your map function, add your new key/value pair into a list object. If the list object has 4 items in it, do processing, emit something, then clean out the list. Otherwise, don't emit anything and move on without doing anything.

Это имеет некоторые накладные расходы по следующим причинам

  • Время обработки самый большой файл потянет время выполнения задания.
  • Множество данных может передаваться между узлами данных.
  • Кластер не используется должным образом, так как # из карт = # файлов.

** Приведенный выше код из Hadoop : The Definitive Guide

+0

Спасибо! Но я использую новый API. – Gitmo

+0

Эта идея кажется многообещающей. Как насчет использования NLinesInputFormat, чтобы указать количество строк для каждого преобразователя. Таким образом, он не будет зависеть от самого большого файла. Проблема в том, что я использую Hadoop 0.20, который не реализован. Любые мысли? – Gitmo

+0

В 0.20 NLineInputFormat не реализован в новом API. Вы можете попробовать портировать новый API NLinesInputFormat из какой-либо другой версии в 0.20. Это не должно быть так сложно, и вы также узнаете, как скомпилировать и построить банку Hadoop. –

Смежные вопросы