gpt4 book ai didi

python - memcache.get 返回错误的对象(Celery、Django)

转载 作者:太空狗 更新时间:2023-10-29 20:21:33 28 4
gpt4 key购买 nike

这是我们目前拥有的:

  1. 我们正在尝试获取缓存的 Django 模型实例,缓存键包括模型名称和实例 ID。使用 Django 的标准 memcached 后端。此程序是非常广泛使用的常用程序的一部分,不仅在 celery 中。
  2. 有时(随机和/或很少)cache.get(key) 返回错误的对象:int 或不同的模型实例,甚至出现相同模型不同 ID 的情况。我们通过检查模型名称和 ID 与缓存键的对应关系来捕捉这一点。
  3. bug 只出现在我们三个 celery 任务的上下文中,从不在 python shell 或其他 celery 任务中重现。 UPD:仅出现在长时间运行的 CPU-RAM 密集型任务下
  4. 缓存存储正确的值(我们在错误刚刚出现时手动检查)
  5. 使用相同的参数再次调用相同的任务可能不会重现问题,尽管概率要高得多,因此错误出现往往会在同一时间段内“分组”
  6. 重启 celery 解决随机时间段(分钟 - 周)的问题
  7. *NEW* 这与内存溢出无关。发生这种情况时,我们始终至少有 2Gb 的可用 RAM。
  8. *NEW* 我们在静态代码中有 cache_instance = cache.get_cache("cache_entry")。在调查过程中,我发现错误发生在 cache_instance.get(key) 返回错误值的时刻,尽管 get_cache("cache_entry").get(key) 在下一行返回正确的一个。这意味着要么 bug 消失得太快,要么由于某种原因 cache_instance 对象被损坏。django的缓存线程返回的缓存实例对象不安全吗?
  9. *NEW* 我们记录了非常奇怪的情况:作为缓存中的另一个错误对象,我们得到了没有设置 ID 的模型实例。这意味着,该实例从未保存到数据库,因此无法缓存。 (我希望)
  10. *NEW* 这几天至少记录了一个MemoryError

我知道,所有这些听起来都像是某种魔法。真的,任何关于如何实现或如何调试的想法都将不胜感激。

PS:我目前的假设是这与多处理有关:一旦在静态代码中创建缓存实例并且在 Worker 进程 fork 之前,这将导致所有 worker 共享同一个套接字(听起来合理吗?)

最佳答案

终于解决了:

  1. Celery 具有动态缩放功能 - 它能够根据负载添加/杀死 worker
  2. 它通过 fork 现有的来做到这一点
  3. 打开的套接字和文件被复制到派生进程,因此两个进程共享它们,当一个进程读取另一个进程的响应时,这会导致竞争条件。简单地说,一个进程可能会读取为第二个进程准备的响应,反之亦然。
  4. from django.core.cache import cache 此对象存储预连接的 memcached 套接字。当您的进程可以动态 fork 时不要使用它..并且不要使用存储的连接、池和其他。
  5. 或者将它们存储在当前 PID 下,并在每次访问缓存时检查它

关于python - memcache.get 返回错误的对象(Celery、Django),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23358787/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com