Статьи

Каковы расширенные функции Apache Hadoop MapReduce?

обзор

Базовое программирование MapReduce объясняет детали рабочего процесса. Но это не покрывает фактические рабочие детали в рамках программирования MapReduce. В этой статье объясняется перемещение данных через архитектуру MapReduce и вызовы API, используемые для фактической обработки. Мы также обсудим методы настройки и переопределение функций для конкретных приложений.

Вступление

Расширенные функции MapReduce описывают выполнение и подробности более низкого уровня. В обычном программировании MapReduce для написания приложений достаточно знать только API и их использование. Но внутренние детали MapReduce необходимы для понимания реальных рабочих деталей и получения уверенности.

Теперь давайте обсудим расширенные функции в следующих разделах.

Пользовательские типы (данные)

Для предоставленных пользователем Mapper и Reducer платформа Hadoop MapReduce всегда использует типизированные данные. Данные, которые проходят через Mappers и Reducers, хранятся в объектах Java.

  • Интерфейс с возможностью записи. Интерфейс с возможностью записи является одним из наиболее важных интерфейсов. Объекты, которые можно маршалировать в / из файлов и по сети, используют этот интерфейс. Hadoop также использует этот интерфейс для передачи данных в сериализованной форме. Некоторые из классов, которые реализуют интерфейс Writable, упомянуты ниже
  1. Текстовый класс (хранит строковые данные)
  2. LongWritable
  3. FloatWritable
  4. IntWritable
  5. BooleanWritable

Пользовательский тип данных также может быть создан с помощью интерфейса Writable . Hadoop способен передавать любой пользовательский тип данных (который соответствует вашему требованию), который реализует интерфейс с возможностью записи.

Ниже приведен интерфейс Writable, который имеет два метода readFields и write. Первый метод (readFields) инициализирует данные объекта из данных, содержащихся в двоичном потоке in. Второй метод (запись) используется для восстановления объекта в двоичном потоке out. Самый важный контракт всего процесса заключается в том, что порядок чтения и записи в двоичный поток одинаков.

Листинг 1: Показываемый интерфейс для записи

1
2
3
4
5
6
7
public interface Writable {
 
void readFields(DataInput in);
 
void write(DataOutput out);
 
}

Пользовательские типы (ключ)

В предыдущем разделе мы обсудили пользовательский тип данных для удовлетворения требований к данным конкретного приложения. Он управляет только частью стоимости. Теперь мы также обсудим пользовательский тип ключа. В Hadoop MapReduce редуктор обрабатывает ключ в отсортированном порядке. Таким образом, пользовательский тип ключа должен реализовывать интерфейс с именем WritableComparable . Типы ключей также должны реализовывать hashCode ().

Ниже показан интерфейс WritableComparable . Он представляет собой Writable, который также сопоставим.

Листинг 2: Отображение интерфейса WritableComparable

1
2
3
public interface WritableComparable<T>
 
extends Writable, Comparable<T>

Как использовать пользовательские типы

Мы уже обсуждали пользовательские значения и типы ключей, которые могут обрабатываться Hadoop. Теперь мы обсудим механизм, чтобы Hadoop мог его понять. Объект JobConf (который определяет задание) имеет два метода, называемых setOutputKeyClass () и setOutputValueClass (), и эти методы используются для управления значением и ключевыми типами данных. Если Mapper создает различные типы, которые не соответствуют Reducer, то методы JobConf setMapOutputKeyClass () и setMapOutputValueClass () могут быть использованы для установки типа ввода, как ожидается в Reducer.

Быстрее производительность

Процесс сортировки по умолчанию немного медленнее, поскольку сначала он читает тип ключа из потока, затем анализирует поток байтов (используя метод readFields () ) и, наконец, вызывает метод compareTo () класса ключа. Более быстрый подход заключался бы в определении порядка между ключами путем проверки байтовых потоков без анализа всего набора данных. Для реализации этого более быстрого механизма сравнения класс WritableComparator может быть расширен с помощью компаратора, специфичного для ваших типов данных. Ниже приводится объявление класса.  

Листинг 3: Отображение класса WritableComparator

1
2
3
4
5
public class WritableComparator
 
extends Object
 
implements RawComparator

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

Форматы ввода

InputFormat является одним из наиболее важных интерфейсов, которые определяют входную спецификацию задания MapReduce. Hadoop предлагает различные типы InputFormat для интерпретации различных типов входных данных. Наиболее распространенным и используемым по умолчанию является TextInputFormat, который используется для чтения строк из текстового файла. Точно так же SequenceFileInputFormat используется для чтения двоичных форматов файлов.

Основной задачей InputFormat является чтение данных из входного файла. Реализация пользовательского InputFormat также возможна в соответствии с потребностями вашего приложения. Для реализации TextInputFormat по умолчанию ключ является байтовым смещением строки, а значение — содержимым строки, оканчивающимся символом ‘\ n’. Для пользовательской реализации разделителем может быть любой символ, и InputFormat будет анализировать соответственно.

Другая задача InputFormat — разделить входной файл (источник данных) на фрагменты, которые являются входными данными для задач сопоставления. Эти фрагменты / разбиения инкапсулированы в экземплярах интерфейса InputSplit. Источником входных данных может быть что угодно, например таблица базы данных, XML-файл или другой файл. Таким образом, разделение будет выполняться в соответствии с требованиями приложения. Наиболее важным моментом является то, что операция разделения должна быть быстрой и дешевой.

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

  • Custom InputFormat: в основных приложениях InputFormat используется напрямую. Но для пользовательского чтения лучшим способом является создание подкласса FileInputFormat . Этот абстрактный класс предоставляет функции для работы с файлами в соответствии с требованиями приложения. Для пользовательского анализа необходимо переопределить метод getRecordReader (), который возвращает экземпляр RecordReader . Этот RecordReader отвечает за чтение и анализ.
  • Альтернативный источник (данные): InputFormat описывает две вещи: первая — это представление данных в Mapper, а вторая — это источник данных. Большинство реализаций основаны на FileInputFormat , где источником данных является локальная файловая система HDFS (Hadoop Distributed File System). Но для других типов источников данных требуется специальная реализация InputFormat. Например, база данных NoSQL, такая как HBase, предоставляет TableInputFormat для чтения данных из таблиц базы данных. Таким образом, источником данных может быть все, что может быть обработано пользовательской реализацией.

Выходные форматы

OutputFormat отвечает за операцию записи. Мы уже обсуждали, что интерфейсы InputFormat и RecordReader отвечают за чтение данных в программу MapReduce. После обработки данных операция записи в постоянное хранилище управляется интерфейсами OutputFormat и RecordWriter . Формат по умолчанию — TextOutputFormat, который записывает пары ключ / значение в виде строк в выходной файл. Другой выходной формат — SequenceFileOutputFormat, и он хранит данные в двоичном виде. Все эти классы используют методы write () и readFields () классов Writable .

Реализация OutputFormat должна быть настроена для записи данных в произвольном формате. Абстрактный класс FileOutputFormat должен быть расширен для настройки. Метод JobConf.setOutputFormat () необходимо изменить, чтобы использовать другой пользовательский формат.

Разделение данных

Разделение можно определить как процесс, который определяет, какой экземпляр редуктора получит какую промежуточную пару ключ / значение. Каждый Mapper должен определить конечный редуктор для всех своих выходных пар ключ / значение. Наиболее важным моментом является то, что для любого ключа независимо от его экземпляра Mapper целевой раздел одинаков. Из соображений производительности Mappers никогда не связываются друг с другом в разделе определенного ключа.

Интерфейс Partitioner используется системой Hadoop для определения целевого раздела для пары ключ / значение. Количество разделов должно совпадать с количеством задач сокращения. Каркас MapReduce определяет количество разделов при запуске задания.

Ниже приведена подпись интерфейса Partitioner.

Листинг 4: Отображение интерфейса Partitioner

1
2
3
public interface Partitioner<K2,V2>
 
extends JobConfigurable

Вывод

В этом обсуждении мы рассмотрели наиболее важные функции Hadoop MapReduce. Эти функции полезны для настройки. В практических приложениях MapReduce реализация API по умолчанию не имеет большого применения. Скорее, пользовательские функции (которые основаны на открытых API) оказывают значительное влияние. Все эти настройки могут быть сделаны легко, как только концепции станут ясными. Надеюсь, что эта статья будет полезна для понимания расширенных функций и их реализации.