PHP Parallel/Distributed Tool & MySQL и как заблокировать функцию на нескольких серверах

Я создавал инструменты PHP с серверной частью MySQL. Используя multi-curl, я могу одновременно запускать десятки, а иногда и сотни каждого скрипта только на одном старом ПК (на котором теперь установлена ​​последняя версия рабочего стола Ubuntu). Каждая машина и каждая виртуальная машина на каждой машине могут запускать десятки одновременных экземпляров.

В результате у меня быстро заканчиваются подключения к MySQL. Когда я увеличил количество соединений в MySQL, я заморозил четырехъядерный компьютер, который использовал для размещения сервера MySQL. С тех пор я перешел к схеме, в которой у меня есть БД, предназначенная для управления запросами других БД, и с помощью заданий cron, которые выполняются часами, я поддерживаю несколько открытых соединений на машину. На данный момент я все еще нахожусь в фазе легкого тестирования, и я не пытался сделать сотни одновременных запросов, чтобы увидеть, как сервер MySQL обрабатывает это.

Вместо этого я столкнулся с другой проблемой, из-за которой я пробовал несколько решений для всех с примерно одинаковыми результатами. Проблема заключается в том, что в БД вводятся повторяющиеся данные, потому что у меня есть параллельные экземпляры инструмента, работающие на разных машинах. Например, я загружаю большой кусок новых данных в свою БД, и для этих данных необходимо выполнить несколько задач, таких как привязка адреса электронной почты к профилю пользователя. Я решил, что фоновый процесс cron обрабатывает это понемногу, и каждая машина делает это каждые 5 минут. Поскольку все они запускаются в одно и то же время, все они получают одни и те же данные электронной почты и фильтруют их, используя одну и ту же логику, определяющую, какие адреса электронной почты имеют более высокий приоритет. Затем каждая машина начинает делать то, что нужно сделать с выбранными электронными письмами. Поскольку все они запускаются одновременно, они часто захватывают одни и те же данные и пытаются сделать одни и те же ссылки. Это вызывает исключение первичного ключа в таблице связей, но не в некоторых других. Таким образом, я получаю дублирующиеся данные в некоторых таблицах и иногда неполную связь.

Я пробовал рандомизировать данные SELECT, чтобы машины работали с разными наборами данных. Однако это, конечно, неоптимально по отношению к тому, что я хотел бы, чтобы инструмент выполнял, поэтому мне нужно запускать инструмент чаще, чтобы определенные задачи выполнялись в желаемые сроки. Я попытался создать в БД флаг, указывающий, что 1 сервер активно использует данные, поэтому все остальные серверы должны ждать. Иногда это работает, но иногда 2 машины одновременно опрашивают этот флаг. Так как мы говорим о нескольких машинах, я не буду работать. И из того, что я читал, блокировка таблицы в БД тоже не может быть хорошим решением.

Поэтому я пришел в StackOverflow за советом, а не продолжать биться головой о стену.

== Обновление ==

Gearman выглядел как отличное решение, поэтому я дал ему большой палец вверх в качестве ответа. Однако мне так и не удалось заставить его работать с моей установкой PHP. Я попробовал несколько наборов предложений/инструкций в Интернете, многие из которых даже не устанавливали Gearman. Насколько я мог судить, предложение использовать apt-get install gearman-server помогло установить gearman, т. е. ошибок не было, и gearmand запустился. Однако, когда я пытался использовать клиенты Gearman и Workers в сценариях, я получал ошибки, связанные с невозможностью найти эти классы.

После этого я добавил файл gearman.ini в правильный каталог. В нем была 1 строка extension=gearman.so. Это привело к другой ошибке, когда PHP сказал мне, что не может найти gearman.so. Я попытался использовать sudo find / -name gearman.*, чтобы найти gearman.so, но безуспешно - он вернул файлы C, но не gearman.so.

В это время мне очень, очень, очень хотелось бы реализовать gearman, но, поскольку я не могу заставить его работать, я застрял в своем PHP-коде взлома и косой черты для реализации моего распределенного набора инструментов. Мое «решение» на сегодняшний день состоит в том, чтобы создать флаг, который устанавливается в «ОККУПИРОВАНО», когда 1 экземпляр инструмента делает что-то, что может вызвать проблемы с дублированием данных. Я создал 5 одинаковых флагов с постфиксами _1, _2,..., чтобы 5 экземпляров могли работать одновременно. (Я использую _1, _2,... для создания смещения в возвращаемых данных БД, чтобы никакие два экземпляра инструмента не работали с одним и тем же набором данных. Другими словами, если оператор SELECT возвращает более 100 строк, а я только работать с 10 за раз, тогда _1 работает с строками 1-10, _2 работает с 11-20, ... Не идеально, но это должно позволить нескольким серверам работать с БД одновременно без создания дубликатов данных.)

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


person Gabe Spradlin    schedule 13.03.2012    source источник


Ответы (1)


Вы должны использовать систему очередей для вставки каждого набора данных в качестве элемента в очередь и использовать настройку распределенного сервера для извлечения заданий из очереди и выполнения запросов к базе данных. Использование очереди предотвратит выполнение одной и той же работы несколькими работниками.

Взгляните на Gearman для примера

person Mike B    schedule 13.03.2012
comment
Я посмотрю, но сейчас у меня есть БД для очереди. Затем кроны тянут задачи и выполняют их. Однако одна и та же задача может быть поставлена ​​в очередь несколькими машинами. Устранение повторяющихся записей в очереди может быть довольно сложным и медленным, поскольку я могу захотеть, чтобы некоторые записи были дублированы (или почти так). Спасибо за ссылку, сейчас поищу. - person Gabe Spradlin; 13.03.2012
comment
Гирман прекрасно выглядит. К сожалению, я безуспешно пытался установить его (рабочий стол Ubuntu 10.04) в течение последнего часа. - person Gabe Spradlin; 14.03.2012
comment
@gabe Я считаю, что это в репозиториях aptitude: apt-get install gearman-server (пробовал с 11.10, не уверен насчет 10.04) - person Mike B; 14.03.2012
comment
Спасибо, это сработало лучше, чем другие 5 предложений по установке Gearman. Тем не менее, я добавил расширение=gearman.so в файлы INI, но он не может его найти. И sudo find / -name gearman.* тоже не находит. Мне все еще нужно его скомпилировать? - person Gabe Spradlin; 14.03.2012