Celery periodic_task并行运行多次

时间:2011-10-10 22:02:57

标签: python celery

我使用Celery的线程有一些非常简单的定期代码;它只是打印“Pre”和“Post”并在其间睡觉。它改编自this StackOverflow questionthis linked website

from celery.task import task
from celery.task import periodic_task
from django.core.cache import cache
from time import sleep
import main
import cutout_score
from threading import Lock

import socket
from datetime import timedelta
from celery.decorators import task, periodic_task

def single_instance_task(timeout):
  def task_exc(func):
    def wrapper(*args, **kwargs):
        lock_id = "celery-single-instance-" + func.__name__
        acquire_lock = lambda: cache.add(lock_id, "true", timeout)
        release_lock = lambda: cache.delete(lock_id)
        if acquire_lock():
            try:
                func()
            finally:
                release_lock()
    return wrapper
  return task_exc

LOCK_EXPIRE = 60 * 5 # Lock expires in 5 minutes
@periodic_task(run_every = timedelta(seconds=2))
def test():
    lock_id = "lock"

    # cache.add fails if if the key already exists
    acquire_lock = lambda: cache.add(lock_id, "true", LOCK_EXPIRE)
    # memcache delete is very slow, but we have to use it to take
    # advantage of using add() for atomic locking
    release_lock = lambda: cache.delete(lock_id)

    if acquire_lock():
        try:
            print 'pre'
            sleep(20)
            print 'post'
        finally:
            release_lock()
        return
    print 'already in use...'

此代码从不打印'already in use...';当我使用@single_instance_task装饰器时会出现同样的现象。

你知道什么是错的吗?

编辑:我简化了问题,以便它不会写入内存(使用全局或django缓存);我仍然没有看到'already in use...'


编辑:当我将以下代码添加到我的Django settings.py文件中时(通过更改https://docs.djangoproject.com/en/dev/topics/cache/中的代码,一切都按预期工作,但仅当我使用端口11211时(奇怪的是,我的服务器在端口8000上)

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '127.0.0.1:11211'
        ]
    }
}

1 个答案:

答案 0 :(得分:3)

你是如何运行芹菜的?我不熟悉线程选项。

如果它正在运行多进程,则没有“全局”变量是工作者之间的共享内存。

如果您希望所有工作人员共享一个计数器,那么我建议您使用cache.incr

E.g:

In [1]: from django.core.cache import cache

In [2]: cache.set('counter',0)

In [3]: cache.incr('counter')
Out[3]: 1

In [4]: cache.incr('counter')
Out[4]: 2

<强>更新

如果你通过休眠强制你的任务重叠会发生什么,例如:

print "Task on %r started" % (self,)
sleep(20)
print "Task on %r stopped" % (self,)

如果你没有得到“已经在使用...”,那就更经常地运行20秒,然后你知道缓存没有按预期运行。


另一次更新

您是否在django设置中设置了缓存后端?例如。分布式缓存

如果没有,您可能正在使用Dummy Cache实际上没有进行任何缓存,只需实现接口 ...这听起来像是一个令人信服的问题原因。