Я настроил установку Hadoop в псевдораспределенном режиме. Короче вопрос такой: Как решить, какие подзадачи возложить на мапперы, а какие на редукторы?
Подробности: Что касается этого курса Udacity:Введение в Hadoop и MapReduce, проблема заключалась в следующем:
Данные поступают из нескольких филиалов по всему миру, принадлежащих одной и той же компании-магазину. Каждая запись данных хранит продажу (чек) в любом магазине. Данные представлены в виде: (дата, время, store_name, стоимость). Например. (01.01.2012, 12:01, New York Store, 12,99$). Задача состояла в том, чтобы получить продажи в расчете на один магазин.
Решение Udacity было:
Меня смущает такой выбор разделения задач между картографами и редюсерами. Кажется, что редуктор по-прежнему выполняет всю работу по чтению и добавлению, хотя на самом деле по умолчанию это только 1 редуктор, похоже, это решение создает узкое место в редюсере.
Мое ожидаемое решение было:
Мои вопросы:
Основная идея парадигмы программирования MapReduce заключается в том, что данные представляются в виде ряда пар key-value
, где key
указывает конкретный тип для идентификации (например, идентификатор пользователя, если мы хотим создать программу для вычисления чего-либо для каждого пользователя). , или слово, если мы хотим подсчитать каждое вхождение каждого слова, как показано здесь из самого проекта Hadoop).
Чтобы перейти от формы входных данных к желаемым результатам вывода, должны быть какие-то манипуляции, чтобы:
key-value
(чтобы мы отображали данные) иkey-value
в зависимости от цели нашей программы).На основе примера Udacity, который вы указали на свой вопрос, мы знаем форму входных данных:
(date, time, store_name, cost)
И нам нужно найти продажи в магазине. Итак, сначала мы отображаем входные данные в форму пары key-value
таким образом, что store_name
каждой входной записи будет помещен в key
пар key-value
. Результатом этой функции будет фактическое чтение каждой строки и создание пары key-value
, где необходимая информация хранится в ней следующим образом (где store_name
— это key
, а cost
— это value
):
(store_name, cost)
Выполнение этого для каждой строки ввода, вероятно, приведет к key-value
парам, которые имеют то же store_name
, что и key
, и на основе этого мы можем уменьшить эти пары, сгруппировав их по ключу и собрав их, чтобы сложить их все и получить общая сумма продаж в магазине. Вывод этой функции будет таким (где store_name
— это key
, а total_sales
— это value
, рассчитанное как запрограммированное пользователем внутри функции):
(store_name, total_sales)
Что касается разделения задачи между преобразователями и редюсерами, это почти полностью зависит от вас, потому что вы должны помнить, что преобразователи выполняются для всех входных данных (например, чтение всех записей построчно в вашем примере), а редюсеры выполняется для каждой key
из key-value
пар, созданных из картографов. Хорошей новостью здесь является то, что такие проекты, как Hadoop, действительно частично делают это за вас, поэтому все, что вам нужно настроить, — это как отображать данные в функции Map
и как обрабатывать данные, сгруппированные по ключам, в функции Reduce
.
Что касается одного редуктора по умолчанию, вы, возможно, знаете, что вы действительно можете установить количество редукторов, сколько хотите, но они будут просто экземплярами функций Reduce
, выполняемых в разных потоках/процессорах/машинах для разных данных ( и именно поэтому Hadoop используется в приложениях для работы с большими данными, потому что эти огромные объемы входных данных лучше обрабатываются путем параллельной обработки через кластер компьютеров).
Ваше замешательство по поводу механики MapReduce до сих пор понятно, потому что на самом деле функции Map
и Reduce
, используемые здесь, получены из области функционального программирования вычислений, и многие люди не привыкли к этому. Подумайте о том, чтобы изучить больше примеров простых приложений MapReduce, чтобы лучше понять их механику, например, пример WordCount или эту простую программу задания MapReduce, которую я написал, чтобы ответить на другой вопрос, где мы подсчитываем общее количество олимпийских золотых побед каждого спортсмена).
Что же касается возможности большего количества задач, то тут уж решать вам, где вырезать и делиться кусками исходных данных с мапперами (подробнее вы можете узнать из ответов в этом вопросе) или сколько редукторы для инициализации для параллельной обработки ваших данных (конечно, для более чем 1 редуктора по умолчанию).