以下是我们目前的情况:
cache_instance = cache.get_cache("cache_entry")
。在调查期间,我发现错误发生的那一刻cache_instance.get(key)
返回错误的值,尽管下一行的get_cache("cache_entry").get(key)
返回正确的值。这意味着错误消失太快或由于某种原因cache_instance对象被破坏。
是不是django的缓存线程返回的缓存实例对象安全吗?MemoryError
我知道,所有这些听起来都像是某种魔法......而且,真的,任何想法如何可能或如何调试都将非常感激。
PS:我目前的假设是这与多处理有关:只要在静态代码中创建缓存实例,并且在工作进程分叉之前,这将导致所有工作者共享相同的套接字(听起来是否合理?)答案 0 :(得分:5)
终于解决了:
from django.core.cache import cache
此对象存储预先连接的memcached套接字。当您的流程可以动态分叉时,请不要使用它。并且不要使用存储的连接,池和其他。 答案 1 :(得分:3)
这一直困扰着我一段时间,直到我找到了这个问题和答案。我只想补充一些我学到的东西。
您可以使用本地memcached实例轻松重现此问题:
request_finished
你可以做的就是关闭缓存客户端,就像Django在cache.close()
信号中所做的那样:
https://github.com/django/django/blob/master/django/core/cache/init.py#L128
如果你在分叉后放置cache.close()
,一切都按预期工作。
对于芹菜,你可以connect to a signal that is fired after the worker is forked并执行def post_fork(server, worker):
from django.core.cache import cache
cache.close()
。
当preload处于活动状态并且在分配工作人员之前初始化缓存时,这也会影响gunicorn。
对于gunicorn,你可以use post_fork
in your gunicorn configuration:
club.com