当我有多个外键的Django对象时,如何命名/排列我的memcached键?

时间:2014-06-09 19:59:10

标签: python django caching memcached python-memcached

我有一个不做任何数据库缓存的现有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()调用都会有一个这样的键。我是否必须手动使它们无效?是不是有一种系统的方法可以同时命名和无效这些密钥,而不必自己记住每个缓存条目?

1 个答案:

答案 0 :(得分:0)

缓存需要一个坚实且精心制定的策略,因为您可能会结束比他们更糟糕的事情。在大多数项目中,您实际上并不需要高级缓存。为什么不在每次更新数据库时缓存页面并删除页面缓存?这将允许查询运行一次,但其余时间将检索缓存。如果仍然坚持使用唯一键进行缓存,则可以通过唯一对象id及其名称来创建键组合。 信号是两种方式,如果你更新或创建和新对象删除缓存,但从你自己的例子可以看出,页面缓存比通过大量对象更容易处理。 除此之外,为什么不在Django cache.get,cache.set,cache.delete函数中使用构建?通过这种方式,您可以保持项目的兼容性,并将代码与缓存引擎分离(可能明天redis将更符合您的需求)。