15 Februar 2010

[Howto] memcached-Probleme zweier Django-Instanzen fixen

Kategorien: HowTos
Tags: Django

Wenn zwei Django-Instanzen sich den gleichen memcached als Cache-Backend teilen, kann es zu Anzeige-Problemen der Templates kommen. Dieser Artikel beschreibt die Bedingungen sowie eine entsprechende Lösung genauer. Wenn zwei Django-Instanzen den gleichen memcached als Caching-Backend nutzen, kann dies zu Anzeige-Problemen führen, falls die Templates Dateien mit gleichem Namen, aber unterschiedlichem Inhalt verwenden: es wird das falsche Template zum eigentlichen Inhalt angezeigt. Dieses Verhalten kann auch in allen Django-Programmen beobachtet werden, welche die Einstellung CACHE_MIDDLEWARE_KEY_PREFIX nicht berücksichtigen. Der entsprechende Bug report erwähnt, dass in einem solchen Fall eine Design-Entscheidung notwendig ist – die oben genannte Einstellung sollte eigentlich nur in Middleware-Installationen genutzt werden, und nicht im Rahmen der Templates. Ohne diese Einstellung können sich aber unterschiedliche Django-Instanzen gegenseitig beeinflussen. Dies ist nicht nur wegen der möglichen optischen Erscheinung der Instanzen von Gewicht, sondern auch wegen der Möglichkeit, CMS-Nutzerberechtigungen in den memcached einzubringen, und so die Rechte anderer Instanzen zu verändern. Eine Möglichkeit ist nun, sicherzustellen, dass die Konfigurationsoption CACHE_MIDDLEWARE_KEY_PREFIX für jeden Zugriff genutzt wird. Der dargestellte Code, als benutzerdefiniertes Cache-Backend genutzt, garantiert dies.

from django.conf import settings
from django.core.cache.backends.memcached import CacheClass as DjangoMemcachedCacheClass
from django.utils.hashcompat import md5_constructor
 
class CacheClass(DjangoMemcachedCacheClass):
    def __init__(self, server, params):
        self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
        super(CacheClass, self).__init__(server, params)
 
    def _genkey(self, origkey):
        return md5_constructor("%s:%s" %(self.key_prefix, origkey)).hexdigest()
 
    def add(self, key, value, timeout=0):
        return super(CacheClass, self).add(self._genkey(key), value, timeout)
 
    def get(self, key, default=None):
        return super(CacheClass, self).get(self._genkey(key), default)
 
    def set(self, key, value, timeout=0):
        return super(CacheClass, self).set(self._genkey(key), value, timeout)
 
    def delete(self, key):
        return super(CacheClass, self).delete(self._genkey(key))
 
    def get_many(self, keys):
        return super(CacheClass, self).get_many(self._genkey(key))
 
    def incr(self, key, delta=1):
        return super(CacheClass, self).incr(self._genkey(key), delta)
 
    def decr(self, key, delta=1):
        return super(CacheClass, self).decr(self._genkey(key), delta)

Darüber hinaus ist es wesentlich schwerer, gefälschten Cache-Inhalt einzufügen, wenn ein md5hex-digest als Schlüssel genutzt wird. Allerdings sollten sowieso nie wichtige Informationen in einem memcached gespeichert werden – in einem solchen Fall wäre locmem, file oder db als Backend wesentlich besser geeignet, da sie eine bessere Rechteverwaltung ermöglichen!

 

Dieser Artikel wurde ursprünglich geschrieben von Bernd Zeimetz.

Kategorien: HowTos
Tags: Django

cR

über den Autor

credativ Redaktion

zur Person

Dieser Account dient als Sammelpunkt für die wertvollen Beiträge ehemaliger Mitarbeiter von credativ. Wir bedanken uns für ihre großartigen Inhalte, die das technische Wissen in unserem Blog über die Jahre hinweg bereichert haben. Ihre Artikel bleiben hier weiterhin für unsere Leser zugänglich.

Beiträge ansehen


Beitrag teilen: