I have an existing Django app that doesn't do any Database caching. I am working to implement memcached to get a performance boost and reduce the amount of expensive database hits.
The strategy I will use is as follows: Every time I am querying the DB with XXX.objects.get() or XXX.objects.filter(), I will first check the cache to see if the result for this same query is already in memcached. If it is, I will just use that. If it is not, I will query the DB and stuff it into memcached with a specifically named key. Any time I update any results of this query, I will invalidate that cache key by using Django's post_save() signal. Sounds fairly simple, right?
Well, I'm struggling with how I should name my cache keys so that this works in an orderly fashion. The issue is that I have Django model objects that have foreign keys to 2 other Django models.
Here are my models:
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)
In the post_save handler() for myObjectC, I need to invalidate the cache keys SOME_NAME1_X and SOME_NAME2_X because they are now out-of-date. Right? I think that's what I need to do.
But what if there are numerous such keys for each instance of each class? After all, there will be one such key for each XXX.objects.get() or XXX.objects.filter() call per instance. Do I have to invalidate them all manually? Isn't there a systematic way to name and invalidate these keys all at once without having to remember each cache entry myself?