Django Celery 缓存锁不起作用?

Vin*_*ang 4 python django celery

我正在尝试使用 Django 缓存来实现锁定机制。在 Celery 官方网站 中,它声称 Django 缓存可以很好地解决这个问题。但是,根据我的经验,它不起作用。我的经验是,如果有多个线程/进程几乎同时(接近~0.003 秒)获取锁,则所有线程/进程都会成功获取锁。对于晚于 ~0.003 秒获取锁的其他线程,它会失败。

我是唯一经历过这种情况的人吗?如果可能,请纠正我。

def acquire(self, block = False, slp_int = 0.001):
    while True:
        added = cache.add(self.ln, 'true', self.timeout)

        if added:
            cache.add(self.ln + '_pid', self.pid, self.timeout)
            return True

        if block:
            sleep(slp_int)
            continue
        else:
            return False


# Set Django backend cache to localcache
CACHES = { 
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/dev/shm/django_cache',                                                                                                                                                                                              
    }   
}
Run Code Online (Sandbox Code Playgroud)

Lou*_*uis 5

问题是 Django 不保证.add(). 实际上是否.add()具有原子性取决于您使用的后端。使用FileBasedCache,.add()不是原子的:

def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
    if self.has_key(key, version):
        return False
    self.set(key, value, timeout, version)
    return True
Run Code Online (Sandbox Code Playgroud)

Worker A 的执行.add()可以在 之后self.has_key(...)但之前被抢占self.set(...).add()一次执行的工人 B将成功设置密钥并返回True。当工人 A 恢复时,它也会设置 key 并 return True

问题报告表明您查看的示例代码假定后端是 Memcached。如果您使用 Memcached 或支持原子的后端,.add()那么它应该可以工作。