Рельсы, на которых запущено несколько задержек - заблокированные таблицы

Эй. Я использую delayed_job для фоновой обработки. У меня 8 серверов процессора, MySQL и я запускаю 7 процессов delayed_job.

RAILS_ENV=production script/delayed_job -n 7 start 

Q1: Мне интересно, возможно ли, что два или более процесса delayed_job начнут обрабатывать один и тот же процесс (одна и та же запись в базе данных delayed_jobs). Я проверил код плагина delayed_job, но не могу найти директиву блокировки так, как это должно быть (таблица блокировки или SELECT... FOR UPDATE).

Я думаю, что каждый процесс должен блокировать таблицу базы данных перед выполнением столбца UPDATE on lock_by. Они блокируют запись, просто обновив поле locked_by (UPDATE delayed_jobs SET locked_by...). Это действительно достаточно? Не требуется блокировка? Зачем? Я знаю, что UPDATE имеет более высокий приоритет, чем SELECT, но я думаю, что это не имеет эффекта в этом случае.

Мое понимание многопоточной ситуации:

Process1: Get waiting job X. [OK]
Process2: Get waiting jobs X. [OK]
Process1: Update locked_by field. [OK]
Process2: Update locked_by field. [OK]
Process1: Get waiting job X. [Already processed]
Process2: Get waiting jobs X. [Already processed]

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

Q2: Является ли 7 delayed_jobs хорошим числом для сервера 8CPU? Почему да/нет.

спасибо 10x!

Ответ 1

Я думаю, что ответ на ваш вопрос находится в строке 168 "lib/delayed_job/job.rb":

self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?)", id, (now - max_run_time.to_i)])

Здесь обновление строки выполняется только в том случае, если другой рабочий не заблокировал задание, и это проверяется, если таблица обновлена. Блокировка таблицы или подобное (что, кстати, значительно уменьшало производительность вашего приложения) не требуется, так как ваша СУБД гарантирует, что выполнение одного запроса изолировано от эффектов от других запросов. В вашем примере Process2 не может получить блокировку для задания X, поскольку он обновляет таблицу заданий тогда и только тогда, когда она не была заблокирована раньше.

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