Должен ли я изучить / использовать MapReduce или какой-либо другой тип распараллеливания для этой задачи? - PullRequest
11 голосов
/ 21 ноября 2010

После разговора с моим другом из Google я хотел бы реализовать какую-то модель Job / Worker для обновления моего набора данных.

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

Прежде чем объяснить свой конкретный набор данных и разобраться в проблеме, я хотел бы уточнить, какие ответы я ищу:

  1. Это поток, который хорошо подходит для распараллеливания с MapReduce?
  2. Если да , будет ли это экономически эффективным для запуска на модуле Amazon mapreduce, который оплачивает по часам и округляет час после завершения задания? (Я не уверен, что именно считается «Работа», поэтому я не знаю точно, как мне будет выставлен счет)
  3. Если нет , есть ли другая система / шаблон, который мне следует использовать? и Есть ли библиотека, которая поможет мне сделать это на python (В AWS, используйте EC2 + EBS)?
  4. Есть ли у вас проблемы с тем, как я спроектировал этот поток работ?

Хорошо, теперь перейдем к деталям:

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

Я могу сделать два звонка:

  • Получить подписчиков - Возвращает всех пользователей, за которыми следит запрошенный пользователь, и
  • Получить избранные элементы - Возвращает все избранные элементы запрошенного пользователя.

После того, как я позвоню получить подписчиков для обновляемого пользователя, мне нужно обновить избранные элементы для каждого отслеживаемого пользователя. Только после того, как все избранные данные будут возвращены всем отслеживаемым пользователям, я смогу начать обработку очереди для этого исходного пользователя. Этот поток выглядит так:

Updating UserX's Queue

Задания в этом потоке включают:

  • Начать обновление очереди для пользователя - запускает процесс, выбирая пользователей, за которыми обновляется пользователь, сохраняя их, а затем создавая Получить избранные задания для каждого пользователя.
  • Получить избранное для пользователя - Запрашивает и сохраняет список избранного для указанного пользователя из сторонней службы.
  • Рассчитать новую очередь для пользователя - Обрабатывает новую очередь, теперь, когда все данные получены, и затем сохраняет результаты в кеше, который используется прикладным уровнем.

Итак, опять мои вопросы:

  1. Это поток, который хорошо подходит для распараллеливания с MapReduce? Я не знаю, позволит ли это мне запустить процесс для UserX, получить все связанные данные и вернуться к обработке очереди UserX только после того, как все это будет сделано.
  2. Если да , будет ли это экономически эффективным для запуска на модуле Amazon mapreduce, который рассчитывается с каждым часом и округляется на час после завершения задания? Есть ли ограничение на количество «потоков», которые я могу ожидать при открытых запросах API, если я использую их модуль?
  3. Если нет , есть ли другая система / шаблон, который мне следует использовать? и Есть ли библиотека, которая поможет мне сделать это на python (На AWS, используйте EC2 + EBS?)?
  4. Есть ли у вас проблемы с тем, как я спроектировал этот поток работ?

Спасибо за чтение, я с нетерпением жду некоторого обсуждения со всеми вами.

Редактировать , в ответ на JimR:

Спасибо за убедительный ответ.В моем чтении, так как я написал оригинальный вопрос, я отказался от использования MapReduce.Я еще точно не решил, как я хочу это построить, но я начинаю чувствовать, что MapReduce лучше для распределения / распараллеливания вычислительной нагрузки, когда я просто пытаюсь распараллелить HTTP-запросы.

То, что было бы моей задачей "уменьшить", та часть, которая собирает все извлеченные данные и преобразует их в результаты, не слишком сложна в вычислительном отношении.Я почти уверен, что это будет один большой запрос SQL, который выполняется в течение секунды или двух на пользователя.

Итак, к чему я склоняюсь, это:

  • Не-MapReduce Job / Worker модель, написанная на Python .Мой друг из Google обратил меня к изучению Python для этого, так как он занимает мало времени и хорошо масштабируется.
  • Использование Amazon EC2 в качестве вычислительного слоя.Я думаю, это означает, что мне также нужен срез EBS для хранения моей базы данных.
  • Возможно, с помощью простой очереди сообщений Amazon.Похоже, этот 3-й виджет Amazon предназначен для отслеживания очередей заданий, перемещения результатов из одной задачи во входные данные другой и изящной обработки неудачных задач.Это очень дешево.Возможно, стоит реализовать вместо собственной системы очереди заданий.

Ответы [ 3 ]

5 голосов
/ 11 декабря 2010

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

Для сервера заданий я рекомендую взглянуть на Gearman. Документация не впечатляет, но презентации отлично ее документируют, и модуль Python также довольно понятен.

По сути, вы создаете функции на сервере заданий, и эти функции вызываются клиентами через API. Функции могут быть вызваны либо синхронно, либо асинхронно. В вашем примере вы, вероятно, хотите асинхронно добавить задание «Начать обновление». Это выполнит любые подготовительные задачи, а затем асинхронно вызовет задание «Получить подписчиков». Это задание будет извлекать пользователей, а затем вызывать задание «Обновить подписчиков». При этом все задания «Получи избранное для пользователя А» и друзей будут отправлены одновременно, и синхронно будет ожидать результатов всех из них. Когда они все вернутся, он вызовет задание «Рассчитать новую очередь».

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

Для очереди SQS - очевидный выбор. Он надежен, очень быстрый доступ из EC2 и дешевый. И намного проще в настройке и обслуживании, чем в других очередях, когда вы только начинаете.

По сути, вы помещаете сообщение в очередь, так же, как если бы вы отправляли задание на сервер заданий выше, за исключением того, что вы, вероятно, ничего не будете делать синхронно. Вместо того, чтобы выполнять «Получить избранное для пользователя A» и т. Д. Синхронно, вы сделаете их асинхронно, а затем получите сообщение, в котором говорится, что все они завершены. Вам понадобится какое-то постоянство (база данных SQL, с которой вы знакомы, или Amazon SimpleDB, если вы хотите полностью использовать AWS), чтобы отслеживать, выполнена ли работа - вы не можете проверить ход выполнения задания в SQS (хотя вы можете в других очередях). Сообщение, которое проверяет, все ли они закончены, выполнит проверку - если они не все закончены, ничего не делайте, и затем сообщение будет повторено через несколько минут (на основе visibility_timeout). В противном случае вы можете поместить следующее сообщение в очередь.

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

В этом случае может быть полезна комбинация сервера очередей и сервера заданий. Вы можете обойтись без наличия постоянного хранилища для проверки хода выполнения задания - сервер заданий позволит вам отслеживать ход выполнения задания. Ваше сообщение «получить избранное для пользователей» может поместить все задания «получить избранное для пользователя A / B / C» на сервер заданий. Затем поместите в очередь сообщение «проверить все избранные выборки выполнено» со списком задач, которые необходимо выполнить (и достаточной информации для перезапуска любых заданий, которые таинственным образом исчезают).

Для бонусных баллов:

Сделать это как MapReduce должно быть довольно легко.

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

"UserX" "UserA"
"UserX" "UserB"
"UserX" "UserC"

Шаг уменьшения идентичности оставит это без изменений. Это сформирует вход второго задания. Карта для второго задания получит избранное для каждой строки (вы можете использовать memcached для предотвращения выборки избранных для комбо UserX / UserA и UserY / UserA через API) и вывести строку для каждого избранного:

"UserX" "UserA" "Favourite1"
"UserX" "UserA" "Favourite2"
"UserX" "UserA" "Favourite3"
"UserX" "UserB" "Favourite4"

Шаг сокращения для этой работы преобразует это в:

 "UserX" [("UserA", "Favourite1"), ("UserA", "Favourite2"), ("UserA", "Favourite3"), ("UserB", "Favourite4")]

В этот момент у вас может быть другое задание MapReduce для обновления базы данных для каждого пользователя с этими значениями, или вы можете использовать некоторые из инструментов, связанных с Hadoop, таких как Pig, Hive и HBase, для управления вашей базой данных дляyou.

Я бы порекомендовал использовать Cloudera Distribution для команд управления Hadoop ec2, чтобы создать и разрушить кластер Hadoop на EC2 (на их AMI настроен Python), и использовать что-то вроде Dumbo (на PyPI).для создания заданий MapReduce, поскольку он позволяет вам тестировать задания MapReduce на локальном компьютере / компьютере разработчика без доступа к Hadoop.

Удачи!

1 голос
/ 19 января 2011

Кажется, что мы идем с Node.js и библиотекой управления потоком Seq . Было очень легко перейти от моей карты / блок-схемы процесса к небольшому фрагменту кода, и теперь это просто вопрос заполнения кода, чтобы подключить нужные API.

Спасибо за ответы, они очень помогли найти решение, которое я искал.

0 голосов
/ 02 декабря 2010

Я работаю с похожей проблемой, которую мне нужно решить.Я также смотрел на MapReduce и использовал сервис Elastic MapReduce от Amazon.

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

Я отвечу на ваши вопросы, когда я понимаю вашу (и мою) проблему, и, надеюсь, этопомогает.

  1. Да, я думаю, это будет хорошо.Вы можете взглянуть на использование многошаговой опции сервиса Elastic MapReduce.Вы можете использовать 1 шаг, чтобы выбрать людей, за которыми следует пользователь, и еще один шаг, чтобы скомпилировать список треков для каждого из этих последователей, и редуктор для этого 2-го шага, вероятно, будет тем, который создаст кэш.

  2. Зависит от того, насколько велик ваш набор данных и как часто вы будете его использовать.Трудно сказать, не зная, насколько большой набор данных (или собирается получить), будет ли он экономически эффективным или нет.Первоначально, это, вероятно, будет довольно рентабельно, поскольку вам не нужно будет управлять собственным кластером hadoop или платить за экземпляры EC2 (при условии, что вы это используете), чтобы они постоянно работали.Как только вы дойдете до того момента, когда вы действительно обрабатываете эти данные в течение длительного периода времени, вам, вероятно, будет все меньше и меньше смысла использовать сервис MapReduce от Amazon, потому что у вас всегда будут постоянно подключенные узлы.

Работа - это в основном ваша задача MapReduce.Он может состоять из нескольких шагов (каждая задача MapReduce является шагом).Как только ваши данные были обработаны и все шаги выполнены, ваша работа завершена.Таким образом, вы эффективно платите за процессорное время для каждого узла в кластере Hadoop.Итак, T * n, где T - это время (в часах), необходимое для обработки ваших данных, а n - это количество узлов, которые вы просите Amazon ускорить.

Надеюсь, это поможет, удачи.Мне бы хотелось услышать, как вы в конечном итоге внедрили свои Mappers и Reducers, поскольку я решаю очень похожую проблему и не уверен, что мой подход действительно лучший.

...