定时执行某项任务是非常常见的一个需求,简单的 crontabl 就可以完成。我们最近的一个 Django 项目中用了 Apscheduler 来调度定时任务,遇到了一些问题。
首先,Apscheduler 定位是一个依赖于你的应用的任务调度库,非常轻巧:
That APScheduler is not a daemon or service itself, nor does it come with any command line tools. It is primarily meant to be run inside existing applications.
Apscheduler 是跟随你的应用来启动的,没有持久化,没有命令行操作任务的工作,运行在应用的内部(这其中很挫的一个问题是,每次运行 Django manage.py 都会启动这玩意,甚至跑 migrate 都会启动,不过这很可能是我们的用法有问题)。如果一些小巧的项目用起来倒是不错,但是如果需要对任务进行管理和控制,就有很多限制了。
Apscheduler 分布式的问题
我们遇到的问题是:Gunicorn 部署 Django 的时候会起来 4 个进程实例,我们 Django 应用内的 Apscheduler 也会跟着起来 4 个,那么遇到定时制定任务的时候,每个任务都会执行 4 次。这就很蛋疼了。
我们先是用了一个临时的解决方案,就是让任务的执行有幂等性。任务是拉去一部分数据到 MySQL 数据库中,那么就在数据库建立一些 Uniqe 索引,后面重复执行的任务放不进去。这样的做法显然会浪费一些资源,但是从结果上看是可以保证正确的,数据肯定不会被重复存储。缺点是每个任务都要考虑到同步的问题,或是类似的唯一索