PHP разветвляет и обрабатывает базу данных MySQL без конфликтов
У меня есть таблица базы данных MySQL, которую мне нужно обработать. Для обработки 3 строк требуется около 1 секунды (из-за соединений CURL, которые мне нужно сделать для каждой строки). Итак, мне нужно разветвить PHP-скрипт, чтобы иметь разумное время (так как я буду обрабатывать до 10 000 строк за один пакет).
Я собираюсь запустить 10-30 процессов одновременно, и, очевидно, мне нужен какой-то способ убедиться, что процессы не перекрываются (с точки зрения того, какие строки они извлекают и изменяют).
Из из того, что я прочитал, есть три способа сделать это. Я пытаюсь решить, какой метод лучше всего подходит для данной ситуации.
Вариант 1: Начните транзакцию и используйте SELECT ... FOR UPDATE
и ограничьте количество строк для каждого процесса. Сохраните данные в массив. Обновите выбранные строки с помощью флага состояния "обработка". Зафиксируйте транзакцию, а затем обновите выбранные строки до статуса "завершено".
Вариант 2: Обновите определенное количество строк с флагом состояния "обработка" и идентификатор процесса. Выберите все строки для этого идентификатора процесса и флага. Работайте с данными как обычно. Обновите эти строки и установите флажок "готово".
Вариант 3: Задайте предложение LIMIT ... OFFSET ...
для запроса SELECT
каждого процесса, чтобы каждый процесс получал уникальные строки для работы. Затем сохраните идентификаторы строк и выполните и UPDATE
, когда закончите.
Я не уверен, какой вариант самый безопасный. Я думаю, что вариант 3 кажется достаточно простым, но мне интересно, есть ли способ, которым это может потерпеть неудачу? Вариант 2 также кажется очень простым, но я не уверен, что блокировка из-за UPDATE
заставляет все замедляться. Вариант 1 кажется лучшим вариантом, но я не очень хорошо знаком с FOR UPDATE
и транзакциями и мог бы воспользоваться некоторой помощью.
ОБНОВЛЕНИЕ: Для ясности, в настоящее время у меня есть только один файл process.php который выбирает все строки и отправляет данные стороннему пользователю через Curl один за другим. Я хотел бы иметь вилку в этом файле, чтобы 10 000 строк можно было разделить между 10-30 дочерними процессами.
2 answers
Другой способ справиться с этим - поместить идентификаторы, которые вам нужно обработать, в очередь redis (список). Затем вы можете вставлять/вставлять элементы из списка. Когда len(список) пуст, вы знаете, что обрабатывать больше нечего.
Существует также проект php resque, который будет реализовывать некоторые из заданий, которые вы хотите выполнить.
В итоге я использовал функции mult_curl (как предложил Брэд) для выполнения этой задачи. Я разделил массив строк на группы по 100 с помощью array_chunk(), а затем настроил задачу multi_curl для их обработки. Я начал использовать ParallelCurl, но в итоге он не работал правильно, поэтому я просто сам закодировал mult_curl.
Для обработки 10 000 соединений curl потребовалось почти 2 часа, чтобы занять всего несколько минут.