Как сделать несколько воркеров на одну задачу?

Подскажите/натолкните на правильное решение.

Как реализовать, что бы несколько воркеров не выполняли одну и ту же задачу.

Допустим нужно отправить письмо с сайта(ну или другое действие, не важно).
Клиент нажимает на кнопку, я это письмо записываю в бд - т.е. создаю задачу.

Дальше у меня крутиться демон(воркер, скрипт который обрабатывает очередь)
while (true) {
//Код, который лезет в бд и ищет задачи, которые не обработаны и обрабатывает. И по выполнению ставит флаг в бд, что задача выполнена.
}

Все вроде ничего.
Проблема возникает если запустить несколько воркеров(несколько демонов). И пока один возьмет эту задачу и будет её обрабатывать, то другой воркер тоже её возьмёт и они вместе будут её обрабатывать. Что собственно так не должно быть.

БД MongoDB, так как весь проект на ней. Но для этой задачи можно и другую поставить. Тот же Redis, может у него есть специальные механизмы, что бы решить данную проблему?

Ну или может как то по другому организовать очередь?

German, RabbitMQ не хочется ставить.
Может знаете какую нибудь проверенную компоненту на гитхабе с решением подобного?
  • Вопрос задан
  • 400 просмотров
Решения вопроса 1
shurshur
@shurshur
Сисадмин, просто сисадмин...
Самый простой и по рабоче-крестьянски наивный способ - создать один общий для всех воркеров файл и ставить на него эксклюзивную блокировку (flock LOCK_EX) в момент взятия из очереди. Например, пусть у задачи есть поле proc_status, которое имеет значения NEW, RUNNING, FINISHED, FAILED. Тогда ставим блокировку, берём из базы задание в статусе NEW, делаем update set proc_status='RUNNING' и снимаем блокировку - никто другой одновременно с нами ту же задачу не возьмёт. Финальный статус можно ставить без блокировки.

Вместо блокировки файла можно использовать блокировки в самой базе, если они там есть (с Mongo не имел дела).

Ещё один не менее простой способ - распределять задачи по идентификаторам. Например, пусть у нас N воркеров, тогда пусть воркер k (где k=0...N-1) обрабатывает только те задания, где id%N=k.

В общем, способы есть.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы