如何命名/排列我的memcached键,针对具有多个外键的Django对象?
我有一个现成的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处理函数里,我需要使缓存键SOME_NAME1_X和SOME_NAME2_X失效,因为它们现在已经过时了,对吧?我觉得我需要这么做。
但是,如果每个类的每个实例都有很多这样的键怎么办?毕竟,每次调用XXX.objects.get()或XXX.objects.filter()时,都会为每个实例生成一个这样的键。我需要手动使它们全部失效吗?有没有什么系统的方法可以一次性命名和使这些键失效,而不需要我自己记住每个缓存条目呢?
1 个回答
缓存需要一个稳妥且精心设计的策略,因为如果处理不好,可能会让事情变得更糟。在大多数项目中,其实并不需要复杂的缓存。为什么不在每次数据库更新时缓存页面,并删除页面缓存呢?这样的话,查询只会执行一次,之后就可以直接从缓存中获取数据。如果你还是想使用缓存,可以用一个独特的键来缓存,这个键可以由唯一对象的ID和名称组合而成。
无论你是更新还是创建新对象,使用信号是个好方法,更新或创建后就删除缓存。不过,正如你自己例子所示,页面缓存比处理大量对象要简单得多。
除此之外,为什么不使用Django内置的cache.get、cache.set和cache.delete函数呢?这样可以保持项目的兼容性,并让你的代码与缓存引擎解耦(也许明天你会更喜欢使用Redis)。