Celerybeat计划多次执行任务?
我有一个任务叫做 calculate_common_locations,它通过 CELERYBEAT_SCHEDULE
每次只运行一次。这个任务的主要功能就是调用数据库里的一个函数:
@app.task
def calculate_common_locations():
db.execute("SELECT * FROM calculate_centroids('b')")
这是 CELERYBEAT_SCHEDULE
中的一个条目:
CELERYBEAT_SCHEDULE = {
'common_locations': {
'task': 'clients.tasks.calculate_common_locations',
'schedule': crontab(hour=23, day_of_week='sun'), #every week
},
[..]
}
这个计划里还有其他一些任务,它们要么是 每天运行一次,要么是 每10秒运行一次。这些任务似乎并不会被重复运行很多次。但是,Celery flower 显示这个任务已经执行了超过20次。第一次按计划开始,运行大约100秒,成功后又重新开始了。
现在只有一个 celerybeat 在运行:
ps -Af | grep celerybeat
foo 24359 779 0 01:53 ? 00:00:04 [celeryd: celery@celery:MainProcess] -active- (worker --beat --app=cloud.celeryapp:app --concurrency=10 -l INFO -s /home/foo/run/celerybeat-schedule --pidfile=/home/foo/run/celerybeat.pid)
这是 celery 启动的方式(通过 supervisord):
celery worker --beat --app=cloud.celery app:app --concurrency=10 -l INFO -s /home/foo/run/celerybeat-schedule --pidfile=/home/foo/run/celerybeat.pid
我测试过不加 --concurrency=10 这个选项,数据库函数仍然被多次执行。
这个函数是从一个很大的表中读取数据(超过100万行),而且这个表经常被插入数据(每秒几次)。Postgres 的锁显示所有的锁都是被授予的。
有可能是因为查询在某个时刻终止,所以任务被重新运行吗?
在以下情况下没有问题:
- 任务从 django shell 运行(直接运行或通过
.delay()
), - 任务的内容被一个轻量级的 SQL 查询替换(select * from test),
- 任务的内容被 sleep(100) 替换。
版本信息:
- celery==3.1.12
- psql (PostgreSQL) 9.3.5
1 个回答
10
如果你考虑一下 crontab(hour=23, day_of_week='sun')
的作用,可能会更容易理解:
>>> crontab(hour=23, day_of_week='sun')
<crontab: * 23 sun * * (m/h/d/dM/MY)>
这意味着这个任务会在每个星期天的晚上11点每分钟执行一次。
如果你想让它只在第一分钟执行,可以这样指定:
crontab(minute=0, hour=23, day_of_week='sun')