【发布时间】:2014-06-15 01:03:42
【问题描述】:
这是我们目前拥有的:
- 我们正在尝试获取缓存的 django 模型实例,缓存键包括模型名称和实例 ID。使用 Django 的标准 memcached 后端。此程序是非常广泛使用的常见程序的一部分,不仅在芹菜中。
- 有时(随机和/或很少)cache.get(key) 返回错误的对象:int 或不同的模型实例,甚至出现相同模型不同 ID 的情况。我们通过检查模型名称和 id 以及缓存键的对应关系来捕捉到这一点。
- 该错误仅出现在我们的三个 celery 任务的上下文中,永远不会在 python shell 或其他 celery 任务中重现。 UPD:仅出现在长时间运行的 CPU-RAM 密集型任务下
- 缓存存储了正确的值(我们在错误刚刚出现时手动检查了该值)
- 使用相同的参数再次调用相同的任务可能不会重现该问题,尽管概率要高得多,因此错误出现往往会在同一时间段内“分组”
- 重启 celery 解决了随机时间段(分钟 - 周)的问题
- *新* 这与内存溢出无关。发生这种情况时,我们始终至少有 2Gb 可用 RAM。
- *NEW* 我们在静态代码中有
cache_instance = cache.get_cache("cache_entry")。在调查过程中,我发现在错误发生的那一刻,cache_instance.get(key)返回了错误的值,尽管下一行的get_cache("cache_entry").get(key)返回了正确的值。这意味着错误消失得太快或由于某种原因 cache_instance 对象已损坏。 django的缓存线程返回的缓存实例对象不安全吗? - *新*我们记录了非常奇怪的情况:作为缓存中的另一个错误对象,我们得到了未设置 id 的模型实例。这意味着,实例从未保存到数据库,因此无法缓存。 (我希望)
- *新*这些天至少记录了一个
MemoryError
我知道,所有这些听起来像是某种魔法。真的,任何想法如何实现或如何调试都将不胜感激。
PS:我目前的假设是这与多处理有关:一旦在静态代码中创建缓存实例并且在工作进程分叉之前,这将导致所有工作人员共享同一个套接字(听起来合理吗?)
【问题讨论】:
-
发现这个:groups.google.com/forum/#!topic/django-developers/x1ZnV7rj8Tk 似乎已连接,但已报告该错误并标记为已修复。
-
尝试以更详细 (-vv) 的方式运行您的内存缓存并根据您的密钥进行过滤,您可能能够更好地解释它到底哪里出错了
-
我猜你没有尝试过不同的硬件?
-
您的 memcached 实际上是一个集群吗?您在 Django 中使用的是哪个 memcached 客户端?我怀疑在高使用率时,您的一个节点响应太慢,因此它被标记为 DOWN。当我们将 memcached 与 celery 一起使用时,我们还使用 Moxi 在较小的 memcached 集群前面处理故障转移。
-
@frederick_c_siu 我们的 memcached 是一个集群,但据我所知,memcached 客户端返回 None 以防相应节点被标记。
标签: python django caching memcached celery