我有一个不做任何数据库缓存的现有Django应用程序。我正在努力实现memcached以提高性能并减少昂贵的数据库命中量。
我将使用的策略如下:每次我使用XXX.objects.get()或XXX.objects.filter()查询数据库时,我将首先检查缓存以查看相同的结果查询已经在memcached中。如果是的话,我会用它。如果不是,我将查询数据库,并使用特别命名的键将其填充到memcached中。每当我更新此查询的任何结果时,我将使用Django的post_save()信号使该缓存键无效。听起来很简单吧?
好吧,我正在努力应该如何命名我的缓存键,以便有条不紊地工作。问题是我有Django模型对象,其中有两个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()调用都会有一个这样的键。我是否必须手动使它们无效?是不是有一种系统的方法可以同时命名和无效这些密钥,而不必自己记住每个缓存条目?
答案 0 :(得分:0)
缓存需要一个坚实且精心制定的策略,因为您可能会结束比他们更糟糕的事情。在大多数项目中,您实际上并不需要高级缓存。为什么不在每次更新数据库时缓存页面并删除页面缓存?这将允许查询运行一次,但其余时间将检索缓存。如果仍然坚持使用唯一键进行缓存,则可以通过唯一对象id及其名称来创建键组合。 信号是两种方式,如果你更新或创建和新对象删除缓存,但从你自己的例子可以看出,页面缓存比通过大量对象更容易处理。 除此之外,为什么不在Django cache.get,cache.set,cache.delete函数中使用构建?通过这种方式,您可以保持项目的兼容性,并将代码与缓存引擎分离(可能明天redis将更符合您的需求)。