当前位置:  开发笔记 > 编程语言 > 正文

memcache.get返回错误的对象(Celery,Django)

如何解决《memcache.get返回错误的对象(Celery,Django)》经验,为你挑选了1个好方法。

这是我们目前的情况:

    我们试图获得缓存的django模型实例,缓存键包括模型名称和实例ID.使用Django的标准memcached后端.该程序是非常广泛使用的常用程序的一部分,不仅在芹菜中.

    有时(随机和/或很少)cache.get(key)返回错误的对象:int或不同的模型实例,甚至出现了same-model-different-id情况.通过检查型号名称和id以及缓存键的对应关系来捕捉这个.

    bug只出现在我们的三个celery任务的上下文中,永远不会在python shell或其他芹菜任务中重现.UPD:仅在长时间运行的CPU-RAM密集型任务下出现

    缓存存储正确的值(我们在错误出现时手动检查)

    使用相同的参数再次调用相同的任务可能不会重现该问题,尽管概率要高得多,因此错误出现倾向于在同一时间段内"分组"

    重启芹菜解决了随机时间段(分钟 - 周)的问题

    *NEW*这与内存溢出无关.发生这种情况时,我们总是至少有2Gb可用内存.

    *新*我们有cache_instance = cache.get_cache("cache_entry")静态代码.在调查过程中,我发现错误发生的那一刻会cache_instance.get(key)返回错误的值,尽管get_cache("cache_entry").get(key)在下一行返回正确的值.这意味着错误消失太快或由于某种原因cache_instance对象被破坏.django的缓存线程返回的缓存实例对象不安全吗?

    *NEW*我们记录了非常奇怪的情况:作为缓存中的另一个错误对象,我们得到了模型实例w/o id set.这意味着,实例从未保存到DB,因此无法缓存.(我希望)

    *新*MemoryError这些天至少记录了一个

我知道,所有这些听起来都像是某种魔法......而且,真的,任何想法如何可能或如何调试这将是非常感激的.

PS:我目前的假设是这与多处理有关:只要在静态代码中创建缓存实例,并且在工作进程分叉之前,这将导致所有工作者共享相同的套接字(这听起来似乎合理吗?)



1> Arseniy..:

终于解决了:

    Celery具有动态扩展功能 - 它能够根据负载添加/杀死工作人员

    它是通过分叉现有的来实现的

    打开的套接字和文件被复制到分叉进程,因此当一个进程读取另一个进程的响应时,两个进程共享它们,这会导致竞争条件.简单地说,一个进程可能会读取针对第二个进程的响应,反之亦然.

    from django.core.cache import cache此对象存储预连接的memcached套接字.当您的进程可以动态分叉时,请不要使用它.并且不要使用存储的连接,池和其他.

    或者将它们存储在当前PID下,并在每次访问缓存时进行检查

推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有