Hadoop: обработка больших сериализованных объектов - PullRequest
2 голосов
/ 10 июня 2010

Я работаю над созданием приложения для обработки (и слияния) нескольких крупных сериализованных объектов Java (размер ГБ порядка) с использованием фреймворка Hadoop.Hadoop store распределяет блоки файла по разным хостам.Но поскольку десериализация потребует присутствия всех блоков на одном хосте, это резко повысит производительность.Как я могу справиться с такой ситуацией, когда разные блоки не могут обрабатываться индивидуально, в отличие от текстовых файлов?

Ответы [ 3 ]

3 голосов
/ 13 июня 2010

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


Обработка файлов в целом:

Один простойХитрость заключается в том, чтобы на первом этапе маппер обрабатывал список имен файлов , а не их содержимое.Если вы хотите, чтобы запустилось 50 заданий карты, создайте по 50 файлов каждый с этой долей имен файлов.Это легко и работает с Java или потоковым Hadoop.

В качестве альтернативы используйте неразделимый формат ввода, такой как NonSplitableTextInputFormat.

Для получения дополнительной информации см. " Как обрабатывать файлы, по одному на карту? "и " Как мне заставить каждую из моих карт работать с одним полным входным файлом? " в Wiki Hadoop.


Местонахождение:

Это оставляетпроблема, однако, в том, что блоки, с которых вы читаете, распределяются по всей HDFS: обычно повышение производительности, здесь реальная проблема.Я не верю, что есть какой-либо способ связать определенные блоки в HDFS.

Можно ли разместить файлы в локальном хранилище каждого узла?На самом деле это самый производительный и самый простой способ решить эту проблему: пусть каждая машина запускает задания для обработки всех файлов, например, /data/1/**/*.data (будучи настолько умным, насколько вы хотите эффективно использовать локальные разделы и количество ядер ЦП).

Если файлы в любом случае исходят из SAN или, скажем, s3, попробуйте просто потянуть оттуда напрямую: он создан для обработки роя.


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

3 голосов
/ 15 июня 2010

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

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

Я использую этот метод при моделировании в Hadoop. Мой сериализованный BLOB-объект - это все данные, необходимые для моделирования, а ключ - просто целое число, представляющее номер моделирования. Это позволяет мне использовать Hadoop (в частности Amazon Elastic Map Reduce) в качестве механизма сетки.

2 голосов
/ 10 июня 2010

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

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

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

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

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