Hadoop читает несколько строк одновременно - PullRequest
7 голосов
/ 15 ноября 2011

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

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

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

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

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

Ответы [ 2 ]

11 голосов
/ 15 ноября 2011

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


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

Возможно, вам придется определить свой собственный 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 строк будет переданата же задача на карте.

3 голосов
/ 16 ноября 2011

Другой способ (простой, но неэффективный в некоторых случаях) - реализовать 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: полное руководство

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...