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 |