2014-06-09 2 views
0

J'ai une application Django existante qui ne fait pas de mise en cache de base de données. Je travaille à l'implémentation de memcached pour améliorer les performances et réduire le nombre d'accès coûteux aux bases de données.Comment nommer/organiser mes clés memcached lorsque j'ai des objets Django avec plusieurs clés étrangères?

La stratégie que je vais utiliser est la suivante: Chaque fois que j'interroge la base de données avec XXX.objects.get() ou XXX.objects.filter(), je vais d'abord vérifier le cache pour voir si le résultat pour cette même requête est déjà en memcached. Si c'est le cas, je vais simplement l'utiliser. Si ce n'est pas le cas, je vais interroger la base de données et l'insérer dans memcached avec un spécifiquement nommé. Chaque fois que je mettrai à jour les résultats de cette requête, j'invaliderai cette clé de cache en utilisant le signal post_save() de Django. Cela semble assez simple, non? Eh bien, je me bats avec la façon dont je devrais nommer mes clés de cache afin que cela fonctionne de manière ordonnée. Le problème est que j'ai des objets modèles Django qui ont des clés étrangères pour 2 autres modèles Django.

Voici mes modèles:

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) 

Dans le gestionnaire de post_save() pour myObjectC, je dois invalider les clés du cache SOME_NAME1_X et SOME_NAME2_X parce qu'ils sont maintenant hors de ce jour. Droite? Je pense que c'est ce que je dois faire.

Mais qu'en est-il s'il existe de nombreuses clés de ce type pour chaque instance de chaque classe? Après tout, il y aura une telle clé pour chaque appel XXX.objects.get() ou XXX.objects.filter() par instance. Dois-je les invalider tous manuellement? N'y a-t-il pas un moyen systématique de nommer et d'invalider ces clés en une seule fois sans avoir à me souvenir de chaque entrée du cache moi-même?

+0

Avez-vous vraiment besoin de tout mettre en cache? Votre projet est-il si grand? 95% des projets s'en iront avec une mise en cache de modèle simple, et une mise en cache de jeu de requête mineure pour les requêtes complexes. – petkostas

+0

Hmmm. Je n'ai pas considéré cela. Je pensais que c'était la façon de le faire. –

+0

Si vous voulez utiliser le cache, la manière la plus simple est d'utiliser le framework de création de cache (vous pouvez avoir redis, memcached, etc.): https://docs.djangoproject.com/fr/1.6/topics/cache/ – petkostas

Répondre

0

La mise en cache nécessite une stratégie solide et soigneusement conçue, car vous pourriez finir par faire pire que ce qu'elle est. Dans la plupart des projets, vous n'avez pas besoin d'une mise en cache avancée. Pourquoi ne pas mettre en cache la page et supprimer le cache de page chaque fois que votre base de données est mise à jour? Cela permettra à la requête de s'exécuter une fois mais le reste du temps, le cache sera récupéré. Si vous insistez toujours pour la mise en cache, le cache utilisant une clé unique, la combinaison de touches peut être créée par l'identifiant unique des objets et son nom. Les signaux sont la voie à suivre, si vous mettez à jour ou créez et le nouvel objet supprime le cache, mais comme vous pouvez le voir dans votre propre exemple, un cache de page est beaucoup plus facile à traiter que de parcourir un grand nombre d'objets. En dehors de cela, pourquoi n'utilisez-vous pas la construction dans Django cache.get, cache.set, la fonction cache.delete? De cette façon, vous maintenez la compatibilité de votre projet et découplez votre code du moteur de cache (peut-être que demain Redis sera plus préféré à vos besoins).

Questions connexes