Я создавал инструменты 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 секунд. Теперь проблема заключается в частых тайм-аутах при попытке захватить эти состояния флага...