为什么Django返回陈旧的缓存数据? [英] Why is Django returning stale cache data?

查看:163
本文介绍了为什么Django返回陈旧的缓存数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个Django模型,如下所示, MyModel1 & MyModel2

I have two Django models as shown below, MyModel1 & MyModel2:

class MyModel1(CachingMixin, MPTTModel):
    name = models.CharField(null=False, blank=False, max_length=255)
    objects = CachingManager()

    def __str__(self):
        return "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ] )

class MyModel2(CachingMixin, models.Model):
    name = models.CharField(null=False, blank=False, max_length=255)
    model1 = models.ManyToManyField(MyModel1, related_name="MyModel2_MyModel1")
    objects = CachingManager()

    def __str__(self):
        return "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ] )

MyModel2 有一个ManyToMany字段到 MyModel1 标题为 model1

MyModel2 has a ManyToMany field to MyModel1 entitled model1

现在看看当我添加一个新的条目到这个ManyToMany时会发生什么领域。根据Django,它没有效果:

Now look what happens when I add a new entry to this ManyToMany field. According to Django, it has no effect:

>>> m1 = MyModel1.objects.all()[0]
>>> m2 = MyModel2.objects.all()[0]
>>> m2.model1.all()
[]
>>> m2.model1.add(m1)
>>> m2.model1.all()
[]

为什么?这似乎是一个缓存问题,因为我看到在数据库表中有一个新的条目myapp_mymodel2_mymodel1为 m2 & M1 。我应该如何解决?

Why? It seems definitely like a caching issue because I see that there is a new entry in Database table myapp_mymodel2_mymodel1 for this link between m2 & m1. How should I fix it??

推荐答案

django-cache-machine是否真的需要?



Is django-cache-machine really needed?

MyModel1.objects.all()[0]

大致翻译为

SELECT * FROM app_mymodel LIMIT 1

这样的查询总是很快。无论您是从缓存还是从数据库中获取速度,速度都不会有显着差异。

Queries like this are always fast. There would not be a significant difference in speeds whether you fetch it from the cache or from the database.

当您使用缓存管理器时,您实际上会添加一些开销可能会使事情变慢一些。大部分时间这个努力将被浪费,因为可能没有缓存命中,如下节所述。

When you use cache manager you actually add a bit of overhead here that might make things a bit slower. Most of the time this effort will be wasted because there may not be a cache hit as explained in the next section.


每当您运行查询时, CachingQuerySet 将尝试在该查询
中找到缓存。查询由 {prefix}键入:{sql} 。如果它在那里,我们
返回缓存的结果集,每个人都很开心。如果缓存中的查询不是
,则执行运行数据库查询的常规代码行。
当结果集中的对象被迭代时,它们被添加到
a列表中,一旦迭代完成就会被缓存。

Whenever you run a query, CachingQuerySet will try to find that query in the cache. Queries are keyed by {prefix}:{sql}. If it’s there, we return the cached result set and everyone is happy. If the query isn’t in the cache, the normal codepath to run a database query is executed. As the objects in the result set are iterated over, they are added to a list that will get cached once iteration is done.

来源: https://cache-machine.readthedocs.io/en/latest/

因此,如果您的问题中执行的两个查询是相同的,缓存管理器将从memcache获取第二个结果集,前提是缓存尚未被忽略。

Accordingly, with the two queries executed in your question being identical, cache manager will fetch the second result set from memcache provided the cache hasn't been invalided.

同样的链接解释了缓存键如何失效。

The same link explains how cache keys are invalidated.


缓存无效,我们使用flush lists标记对象所属的
缓存查询。这样,找到
对象的所有查询将在该对象发生变化时失效。 Flush
列出将对象键映射到查询键列表。

To support easy cache invalidation, we use "flush lists" to mark the cached queries an object belongs to. That way, all queries where an object was found will be invalidated when that object changes. Flush lists map an object key to a list of query keys.

当对象被保存或删除时,其列表中的所有查询键
将被删除。此外,其外键
关系的刷新列表将被清除。为避免陈旧的外键关系,任何
缓存的对象将被刷新,当对象的外键
指向无效时。

When an object is saved or deleted, all query keys in its flush list will be deleted. In addition, the flush lists of its foreign key relations will be cleared. To avoid stale foreign key relations, any cached objects will be flushed when the object their foreign key points to is invalidated.

很明显,保存或删除对象将导致高速缓存中的许多对象必须被无效。所以你通过使用缓存管理器来减慢这些操作。值得注意的是,无效文件根本没有提到很多领域。有一个公开的问题,从您对这个问题的评论很清楚你也发现了它。

It's clear that saving or deleting an object would result in many objects in the cache having to be invalidated. So you are slowing down these operations by using cache manager. Also worth noting is that the invalidation documentation does not mention many to many fields at all. There is an open issue for this and from your comment on that issue it's clear that you have discovered it too.

Chuck缓存机。缓存所有查询几乎从来不值得。它会导致各种难以发现的bug和问题。最好的方法是优化你的表格并调整你的查询。如果您发现特定的查询手动缓存速度太慢。

Chuck cache machine. Caching all queries are almost never worth it. It leads to all kind of hard to find bugs and issues. The best approach is to optimize your tables and fine tune your queries. If you find a particular query that is too slow cache it manually.

这篇关于为什么Django返回陈旧的缓存数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆