По этому поводу в репозитории celery github есть открытый вопрос.Не знаю, работают ли они над этим, хотя.
В качестве обходного пути вы можете добавить блокировку для задач, чтобы одновременно запускался только 1 экземпляр конкретного PeriodicTask.
Что-то вроде:
if not cache.add('My-unique-lock-name', True, timeout=lock_timeout):
return
Выяснить время ожидания блокировки довольно сложно.Мы используем 0,9 * task run_every секунд, если разные сельдереи будут пытаться запускать их в разное время.0,9 только для того, чтобы оставить некоторый запас (например, когда сельдерей немного отстает от графика один раз, то он идет по расписанию, что приведет к тому, что блокировка все еще активна).
Тогда вы можете использовать экземпляр сельдерея на всех машинах.Каждая задача будет поставлена в очередь для каждого экземпляра celerybeat, но только одна из них завершит выполнение.
Задачи все равно будут учитывать run_every таким образом, в худшем случае: задачи будут выполняться с 0,9 * run_every speed.
Одна проблема в этом случае: если задачи были поставлены в очередь, но не были обработаны в запланированное время (например, из-за недоступности процессоров очереди) - тогда блокировка может быть установлена в неправильное время, что может привести к тому, что 1 следующая задача просто не будет запущена.Чтобы обойти это, вам понадобится какой-то механизм обнаружения, является ли задача более или менее своевременной.
Тем не менее, это не должно быть обычной ситуацией при использовании в производстве.
Другое решениеявляется подклассом планировщика сельдерея и переопределить его метод тиков.Затем для каждого тика добавить блокировку перед обработкой задач.Это гарантирует, что только сельдереи с одинаковыми периодическими задачами не будут ставить в очередь одни и те же задачи несколько раз.Только один сельдерей для каждого тика (тот, кто победит в состоянии гонки) поставит в очередь задачи.В одном сельдерее происходит сбой, при следующем тикете другой выигрывает гонку.
Это, конечно, можно использовать в сочетании с первым решением.
Конечно, чтобы это работало, нужно кеш-бэкэндареплицироваться и / или совместно использоваться для всех серверов.
Это старый вопрос, но я надеюсь, что он кому-нибудь поможет.