0

我有一个不做任何数据库缓存的现有 Django 应用程序。我正在努力实现 memcached 以提高性能并减少昂贵的数据库点击量。

我将使用的策略如下:每次我使用 XXX.objects.get() 或 XXX.objects.filter() 查询数据库时,我都会先检查缓存,看看是否已经有相同查询的结果在内存缓存中。如果是,我会使用它。如果不是,我将查询数据库并使用特定命名的键将其填充到 memcached 中。每当我更新此查询的任何结果时,我都会使用 Django 的 post_save() 信号使该缓存键无效。听起来很简单,对吧?

好吧,我正在为如何命名我的缓存键而苦苦挣扎,以便它以有序的方式工作。问题是我有 Django 模型对象,这些对象具有其他 2 个 Django 模型的外键。

这是我的模型:

memCache = pylibmc.Client(["127.0.0.1"])

class myObjectA(models.Model):  
    field1 = models.CharField(max_length=255)

    def getC_Children(self):
        if "SOME_NAME1_%s" % self.pk in memCache:
           return memCache["SOME_NAME1_%s" % self.pk]
        else:
           newCacheEntry = myObjectC.objects.filter(fk_myObjectA=self)
           memCache["SOME_NAME1_%s" % self.pk] = newCacheEntry
           return newCacheEntry




class myObjectB(models.Model):  
    field2 = models.CharField(max_length=255)

    def getC_Children(self):
        if "SOME_NAME2_%s" % self.pk in memCache:
           return memCache["SOME_NAME2_%s" % self.pk]
        else:
           newCacheEntry = myObjectC.objects.filter(fk_myObjectB=self)
           memCache["SOME_NAME2_%s" % self.pk] = newCacheEntry
           return newCacheEntry



class myObjectC(models.Model):  
    fk_myObjectA = models.ForeignKey(myObjectA, related_name="Blah_Blah") 
    fk_myObjectB = models.ForeignKey(myObjectB, related_name="Blah_Blah2") 
    field3 = models.CharField(max_length=255)

在 myObjectC 的 post_save handler() 中,我需要使缓存键 SOME_NAME1_X 和 SOME_NAME2_X 无效,因为它们现在已经过时了。正确的?我认为这就是我需要做的。

但是,如果每个类的每个实例都有许多这样的键怎么办?毕竟,每个实例的每个 XXX.objects.get() 或 XXX.objects.filter() 调用都会有一个这样的键。我必须手动使它们全部无效吗?是否有一种系统的方法可以一次命名和使这些键无效,而不必自己记住每个缓存条目?

4

1 回答 1

0

缓存需要一个可靠且精心设计的策略,因为您最终可能会做的事情比实际情况更糟。在大多数项目中,您实际上不需要高级缓存。为什么每次更新数据库时不缓存页面并删除页面缓存?这将允许查询运行一次,但其余时间将检索缓存。如果您仍然坚持缓存,使用唯一键进行缓存,则它们的键组合可以由唯一对象 id 和它的名称创建。如果您更新或创建新对象并删除缓存,则信号是任何一种方式,但正如您从自己的示例中看到的那样,页面缓存比通过大量对象更容易处理。除此之外,为什么不使用 Django cache.get、cache.set、cache 中的构建。删除功能?这样您就可以保持项目的兼容性并将您的代码与缓存引擎分离(也许明天 redis 将更适合您的需求)。

于 2014-06-10T08:30:35.023 回答