Как назвать / расположить ключи memcached, когда у меня есть объекты Django с несколькими внешними ключами?
У меня есть приложение Django, которое не выполняет кэширование базы данных. Я работаю над внедрением memcached для повышения производительности и уменьшения количества дорогих обращений к базе данных.
Стратегия, которую я буду использовать, заключается в следующем: каждый раз, когда я запрашиваю БД с помощью XXX.objects.get() или XXX.objects.filter(), я сначала проверяю кеш, чтобы убедиться, что результат для этого же запроса уже в memcached. Если это так, я просто буду использовать это. Если это не так, я сделаю запрос к БД и вставлю его в 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)
В обработчике post_save() для myObjectC мне нужно аннулировать ключи кеша SOME_NAME1_X и SOME_NAME2_X, поскольку они устарели. Правильно? Я думаю, это то, что мне нужно сделать.
Но что, если существует множество таких ключей для каждого экземпляра каждого класса? В конце концов, будет один такой ключ для каждого вызова XXX.objects.get() или XXX.objects.filter () для каждого экземпляра. Должен ли я сделать их все недействительными вручную? Разве не существует систематического способа именования и аннулирования этих ключей сразу, без необходимости запоминать каждую запись в кэше самостоятельно?
1 ответ
Кеширование требует четкой и тщательно продуманной стратегии, потому что вы можете закончить делать вещи хуже, чем они. В большинстве проектов вам не требуется расширенное кэширование. Почему бы вам не кэшировать страницу и не удалять кэш страницы каждый раз, когда обновляется ваша БД? это позволит выполнить запрос один раз, но в остальное время будет восстановлен кэш. Если вы все еще настаиваете на кэшировании, используйте для кеширования уникальный ключ, их комбинация клавиш может быть создана с помощью уникального идентификатора объекта и его имени. Сигналы - это путь в любом случае, если вы обновляете или создаете, а новый объект удаляет кеш, но, как вы можете видеть из своего собственного примера, кеш страницы обрабатывается гораздо проще, чем проходя через большое количество объектов. Кроме того, почему бы вам не использовать встроенные функции Django cache.get, cache.set, cache.delete? таким образом вы сохраняете совместимость вашего проекта и отсоединяете свой код от механизма кэширования (возможно, завтра redis будет более предпочтительным, чем ваши потребности).