Начало работы с MapReduce

Код приложения для MapReduce состоит из трех частей:

  • Mapper

  • Reducer

  • Driver

 
Эти части, как правило, базируются на классах с такими же названиями:

  • Mapper. Этот класс отвечает за выполнение первой стадии обработки данных. Объект InputSplit является логическим представлением входных данных. Он описывает единицу работы, которую выполняет одна задача на стадии Map в задании для MapReduce. RecordReader обрабатывает каждую отдельную запись и генерирует соответствующую пару ключ-значение. MapReduce сохраняет эти промежуточные данные на локальном диске узла.

  • Reducer. Этот класс отвечает за выполнение второй стадии обработки данных. MapReduce поставляет промежуточные данные, сгенерированные процессами mapper, на вход процессам reducer, которые формируют окончательные данные и сохраняют их в HDFS.

  • Driver. Данный класс отвечает за настройку задания для MapReduce, которое будет запущено в Hadoop.

Рассматриваемый пример будет подсчитывать слова в текстовом файле sample.txt с использованием MapReduce. Мы определим уникальные слова и сколько раз каждое слово встречается в тексте. Обработка данных проходит несколько стадий, как представлено на следующей схеме.

MapReduceExample dark
Последовательность обработки данных
MapReduceExample light
Последовательность обработки данных
  1. Как представлено на схеме, входной текст разделен на три части, распределенные по узлам DataNodes.

  2. Каждый экземпляр mapper разбивает полученный текст на токены (слова) и присваивает каждому из них значение 1.

  3. Образуется столько пар ключ-значение (где ключ — это слово, а значение — 1), сколько всего слов в строке без учета уникальности. Например, из первой строки "One Two Three" получим три пары: ("One", 1), ("Two", 1) и ("Three", 1). Если какое-то слово встречается несколько раз, то образуется такое же количество одинаковых пар. Данный процесс работает одинаково на всех узлах.

  4. После фазы map выполняется процесс сортировки и распределения (shuffling) данных так, что все пары с одинаковым ключом будут направлены на вход одного процесса агрегации (reducer).

  5. После распределения каждый reducer получит уникальный ключ и список значений, где каждое значение равно 1, например: ("One", [1,1]), ("Zero", [1,1,1]) и так далее.

  6. Агрегатор складывает все значения в списке. Например, в приведенной схеме агрегатор получает список [1,1] по ключу "One". Он подсчитывает количество единиц в списке и формирует окончательный результат – ("One", 2).

  7. В конечном итоге MapReduce собирает все пары и записывает их в один файл.

Код Mapper

Код mapper выполняет следующие операции:

  1. Создает класс Map, расширяющий класс Mapper из библиотеки MapReduce.

  2. Определяет типы входных и выходных ключей и значений в угловых скобках в определении класса. Как вход, так и выход метода обработки данных внутри класса состоят из пар ключ-данные.

     
    Входные данные:

    • Ключ равен смещению соответствующей ему строки текста во входном файле — тип LongWritable (изменяемое длинное целое число).

    • Значением является строка, на которую указывает ключ — тип Text.

     
    Выходные данные:

    • Ключом является слово, выделенное как токен — тип Text.

    • Значение, закрепленное в коде, равно 1 — тип IntWritable (изменяемое целое число).

      Пример выходных данных: ("Dear", 1), ("Bear", 1) и так далее.

    Мы представили код, написанный на Java, который разделяет текст на токены и назначает каждому значение 1.

Код Reducer

Код агрегации (reducer) выполняет следующие операции:

  1. Создает класс Reduce, расширяющий класс Reducer аналогично тому, как это сделано в Mapper.

  2. Задает типы данных для входных и выходных ключей и значений аналогично тому, как это сделано для Mapper. На входе и выходе основного метода обработки данных используются пары ключ-значение.

     
    Входные данные:

    • Ключом является уникальное слово, выделенное в результате сортировки и распределения данных — тип Text.

    • Значением является список целых чисел, соответствующих ключу — тип IntWritable.

      Пример входных данных: ("Bear", [1, 1]), ("Car", [1, 1, 1]) и так далее.

     
    Выходные данные:

    • Ключом является одно из уникальных слов, обнаруженных во входном текстовом файле — тип Text.

    • Значением является частота вхождения слова в тексте — тип IntWritable.

      Пример выходных данных: ("Bear", 2), ("Car", 3) и так далее.

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

Код Driver

Код driver выполняет следующие операции:

  1. Настраивает задание (job) для MapReduce в Hadoop.

  2. Дает название заданию, определяет типы входных и выходных данных для обработчиков mapper и reducer.

  3. Определяет названия классов для mapper и reducer.

  4. Задает пути к папкам для нахождения входных данных и записи выходных данных.

Метод setInputFormatClass() определяет способ чтения входных данных или единицу работы. Здесь мы выбрали тип TextInputFormat, в результате чего mapper считывает данные из входного файла построчно.

Метод main() является точкой входа. Этот метод активизирует объект Configuration для задания.

Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней