Rails работает несколько delayed_job - блокировка таблиц
Привет. Я использую delayed_job для фоновой обработки. У меня 8 процессорных серверов, MySQL и я запускаю 7 процессов delayed_job
RAILS_ENV=production script/delayed_job -n 7 start
Вопрос1: Мне интересно, возможно ли, чтобы 2 или более процесса delayed_job начали обрабатывать один и тот же процесс (одну и ту же строку записи в базе данных delayed_jobs). Я проверил код плагина delayed_job, но не могу найти директиву блокировки так, как она должна быть (без таблицы блокировки или SELECT...FOR UPDATE).
Я думаю, что каждый процесс должен заблокировать таблицу базы данных перед выполнением UPDATE для столбца lock_by. Они блокируют запись, просто обновляя поле locked_by (UPDATE delayed_jobs SET locked_by...). Этого действительно достаточно? Блокировка не нужна? Зачем? Я знаю, что ОБНОВЛЕНИЕ имеет более высокий приоритет, чем 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 - хорошее число для сервера 8 CPU? Почему да / нет.
Спасибо 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 рабочих являются хорошей отправной точкой, так как рабочие являются однопоточными, вы должны использовать по одному на каждое ядро. В зависимости от вашей настройки, больше или меньше работников лучше. Это сильно зависит от вашей работы. Воспользуйтесь преимуществами нескольких ядер? Или ваша работа большую часть времени ждет внешних ресурсов? Вы экспериментировали с различными настройками и просматривали все задействованные ресурсы.