在指定时间调度单个任务的最佳方法是什么?

0 投票
3 回答
546 浏览
提问于 2025-04-16 14:53

我们来看一个例子:

有用户请求在2011年4月19日20:20发布一篇ID为5的文章。所以我想创建一个任务,在2011年4月19日20:20时改变这篇文章的状态。

我想到以下几种方法:

  1. 使用Celery,并配合RabbitMQ或Django-kombu:利用倒计时和预计时间来实现。具体可以参考这个链接:http://docs.celeryproject.org/en/v2.2.5/userguide/executing.html#eta-and-countdown
  2. 创建一个Django管理任务,检查是否有文章需要发布。然后用定时任务每分钟运行一次这个任务。
  3. 写一个小的Python程序,里面有一个无限循环,每秒或每10秒检查一次。我会把当前10分钟内的所有文章放在内存中,这样可以更快地检查,如果没有需要处理的文章,它就会休眠10分钟。

在这种情况下,你有什么建议?哪种方法在性能和扩展性上更好?假设每秒大约有10万个任务被执行。

3 个回答

1

我建议你使用定时任务来处理这种情况。如果你不想处理系统之间的兼容问题,可以考虑使用像 django-cron 这样的工具。

1

为什么不在一个日期时间字段上设置一个默认值为现在的时间呢?然后为这个模型创建一个管理器,只返回那些活跃的任务,也就是活跃日期早于现在的任务(就像一个叫.get_active_only的方法)。如果你希望某篇文章在未来显示,只需保存一个对象,并设置一个未来的活跃时间。这样一来,你就只会查找活跃的文章,而跳过所有即将到来的文章。

4

我的建议是一开始保持简单,可以用一个管理命令,每分钟通过CRON来执行。当这个方法不够用了,再换成分布式的工作方式。如果你把代码分开写好,这个转变不会太大。

如果你一开始就要处理10万个任务,我建议选择第一种方案,因为这样可以用celery把任务分散到很多服务器上。如果你选择普通的cronjob设置,就只能在同一台服务器上运行所有任务,这样扩展性不好。设置RabbitMQ并维护它比设置cronjob要复杂得多,所以尽量晚一点再考虑这个。

对于第二种方案:Django-Extensions也有类似cronjob的系统,可以作为管理命令来使用,这样你就不用重新发明轮子了。而且Django-Extensions还有很多其他好用的工具,你可能也会想用。

http://packages.python.org/django-extensions/jobs_scheduling.html

如果你选择第三种方案,确保使用一些工具来保持守护进程运行。如果它崩溃了,你需要自动重启它。http://supervisord.org是个不错的选择。

撰写回答