如何为每个Django模型实例安排定期的Celery任务?

时间:2011-12-25 16:56:34

标签: python django celery django-celery

我的数据库中有一堆Feed对象,我试图让每个Feed每小时更新一次。我的问题是,我需要确保没有任何重复更新 - 它需要每小时发生一次,但我也不希望Feed等待两个小时进行更新。 (如果它每小时发生+/-几分钟就可以了,但几分钟内发生两次是不好的。)

我正在使用Django和Celery与Amazon SQS作为经纪人。我将Feed更新代码设置为Celery任务,但是我没有找到一种方法来防止重复,同时保持与在多个节点上运行的Celery兼容。

我目前的解决方案是在Feed模型中添加last_update_scheduled属性,每5分钟运行一次以下任务(伪代码):

threshold = datetime.now() - timedelta(seconds=3600)
for f in Feed.objects.filter(Q(last_update_scheduled__lt = threshold) |
                             Q(last_update_scheduled = None)):
    updateFeed.delay(f)
    f.last_update_scheduled = now
    f.save()

这容易受到许多同步问题的影响。例如,如果我的任务队列得到备份,则此任务可能会同时运行两次,从而导致重复更新。我已经看到了一些解决方案(如Celery's recipean adaptation on Stack Overflow),但memcached解决方案不可靠,例如重新启动memcached时可能会发生重复,或者当它发生内存不足并清除旧数据时可能会发生重复。更不用说我不想为了简单的锁定而将memcached添加到我的生产配置中。

在一个完美的世界里,我希望能够说:

@modelTask(Feed, run_every=3600)
def updateFeed(feed):
    # do something expensive

但到目前为止,我的想象力使我无法实现该装饰器。

1 个答案:

答案 0 :(得分:0)

要明确的是,Celery配方本身并没有使用memcached,而是使用Django的缓存中间件。有许多其他缓存方法可以满足您的需求而没有memcached的缺点。有关详细信息,请参阅the Django caching documentation