Hadoop одна карта и несколько уменьшить - PullRequest
36 голосов
/ 25 февраля 2010

У нас есть большой набор данных для анализа с несколькими функциями уменьшения .

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

Могу ли я сделать это с Hadoop? Я искал примеры и intarweb, но я не мог найти какие-либо решения.

Ответы [ 6 ]

11 голосов
/ 27 февраля 2010

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

Затем вы должны написать задание для каждой отдельной функции сокращения, которая работает с этими данными. Это означало бы сохранение всех отображенных данных в HDFS.

Другой альтернативой может быть объединение всех ваших функций уменьшения в один редуктор, который выводит несколько файлов, используя разные выходные данные для каждой отдельной функции. Несколько выходов упоминаются в этой статье для hadoop 0.19 . Я почти уверен, что эта функция не работает в новом API mapreduce, выпущенном с 0.20.1, но вы все равно можете использовать его в более старом API Mapred.

4 голосов
/ 26 февраля 2010

Ожидаете ли вы, что каждый редуктор будет работать с точно такими же отображенными данными? Но, по крайней мере, «ключ» должен быть другим, поскольку он решает, какой редуктор выбрать.

Вы можете записать вывод несколько раз в маппере и вывести в виде ключа (где $ i для i-го редуктора, а $ key - ваш оригинальный ключ). И вам нужно добавить «Partitioner», чтобы убедиться, что эти n записей распределены в редукторах на основе $ i. Затем с помощью «GroupingComparator» сгруппировать записи по оригинальному ключу $.

Это возможно сделать, но не тривиальным способом за одну MR.

3 голосов
/ 30 марта 2011

Вы можете использовать составные ключи. Допустим, вам нужны два типа редукторов, «R1» и «R2». Добавьте идентификаторы для них в качестве префикса к вашим клавишам o / p в маппере. Таким образом, в маппере ключ «K» теперь становится «R1: K» или «R2: K».

Затем в редукторе передайте значения реализациям R1 или R2 на основе префикса.

1 голос
/ 27 апреля 2011

Полагаю, вы хотите использовать разные редукторы в цепочке. В hadoop «несколько редукторов» означает запуск нескольких экземпляров одного и того же редуктора. Я бы предложил вам запускать по одному редуктору за раз, обеспечивая тривиальную функцию отображения для всех из них, кроме первого. Чтобы минимизировать время передачи данных, вы можете использовать сжатие.

0 голосов
/ 28 февраля 2010

Я все еще не понимаю вашу проблему, вы можете использовать следующую последовательность:

база данных -> карта -> уменьшить (используйте cat или None в зависимости от требования) затем сохраните представление данных, которое вы извлекли. если вы говорите, что он достаточно мал, чтобы поместиться в памяти, то его хранение на диске не должно быть проблемой.

Кроме того, использование вами парадигмы MapReduce для данной проблемы некорректно, использование одной функции карты и нескольких «разных» функций сокращения не имеет смысла, это показывает, что вы просто используете карту для передачи данных на разные машины, чтобы сделать разные вещи. для этого вам не требуется hadoop или любая другая специальная архитектура.

0 голосов
/ 26 февраля 2010

Конечно, вы можете определить несколько редукторов. Для работы (Hadoop 0.20) просто добавьте:

job.setNumReduceTasks(<number>);

Но. Ваша инфраструктура должна поддерживать несколько редукторов, а это значит, что вам нужно

  1. имеется более одного процессора
  2. соответственно откорректировать mapred.tasktracker.reduce.tasks.maximum в mapred-site.xml

И, конечно, ваша работа должна соответствовать некоторым спецификациям. Не зная, что именно вы хотите сделать, я могу дать только общие советы:

  • ключ map-output должен быть либо разделен% numreducers, либо вы должны определить свой собственный разделитель: job.setPartitionerClass(...) например со случайным разделителем ...
  • данные должны быть сокращены в многораздельном формате ... (необходимы ссылки?)

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

Посмотрите также на класс Combiner, который является локальным Редуктором. Это означает, что вы можете агрегировать (уменьшать) уже в памяти более частичные данные, испускаемые картой. Очень хороший пример - WordCount-Example. Карта выдает каждое слово в качестве ключа и его счет как 1: (слово, 1). Combiner получает частичные данные с карты, генерирует (,) локально. Редуктор делает то же самое, но теперь некоторые (комбинированные) счетчики слов уже> 1. Сохраняет полосу пропускания.

...