我有一些使用Celery线程的非常简单的定期代码.它只打印“ Pre”和“ Post”,然后在它们之间睡眠.改编自this * question和this 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...'
此代码永远不会打印“已经使用中…”;当我使用@single_instance_task装饰器时,会发生相同的现象.
你知道怎么了吗
编辑:我简化了问题,以便它不会写入内存(使用全局或django缓存);我仍然永远不会看到“已经在使用…”
编辑:当我将以下代码添加到我的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'
]
}
}
解决方法:
芹菜好吗我对线程选项不熟悉.
如果它正在运行多进程,则没有在工作程序之间共享内存的“全局”变量.
如果您希望所有工作人员之间共享一个计数器,那么建议您使用cache.incr.
例如.:
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,只需实现接口…这听起来像是引起问题的令人信服的原因.