Rails работает несколько delayed_job - блокировка таблиц - PullRequest
10 голосов
/ 25 апреля 2010

Эй. Я использую 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 ...). Этого действительно достаточно? Блокировка не нужна? Зачем? Я знаю, что 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? Почему да / нет.

Thx 10x!

1 Ответ

11 голосов
/ 25 апреля 2010

Я думаю, что ответ на ваш вопрос находится в строке 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 рабочих являются хорошей отправной точкой, так как рабочие являются однопоточными, вы должны использовать по одному на каждое ядро. В зависимости от вашей настройки, больше или меньше работников лучше. Это сильно зависит от вашей работы. Воспользуйтесь преимуществами нескольких ядер? Или ваша работа большую часть времени ждет внешних ресурсов? Вы экспериментировали с различными настройками и просматривали все задействованные ресурсы.

...