Magento Asynchronous Cache

So, und ein Magento Caching Artikel (siehe auch hier und hier) ...

Dieses Mal geht es um das asynchrone Löschen des Caches. Hintergrund ist folgender: 

Magentos Caching System beruht weitestgehend auf Tags. Als Entwickler kann man selbst mit diesen Tags arbeiten, aber auch Magento-intern werden diese Tags verwendet, um bestimmte Teile des Caches gezielt zu löschen. 

Das Löschen passiert an vielen Stellen automatisch, zum Beispiel beim Speichern eines Produktes oder einer Konfigurationseinstellung und sogar beim Login. 

Problem:

Cache Tags sind erstmal eine gute Sache. Zum Problem werden sie allerdings, wenn der Cache richtig groß wird und das tag-basierte Löschen des Caches dann sehr lange dauert. Verwendet man zum Beispiel das Dateisystem als Cache-Backend (oder als Second-Level-Cache-Backend), dann müssen alle Metadaten-Dateien gelesen und nach den Tags durchsucht werden. Bei einem Volumen von einigen GB kann das teilweise mehrere Minuten dauern.

Ein weiteres Problem ist das Importieren von Produkten. Verwendet man zum Beispiel einen individuellen Importer, der das Produktmodel verwendet, dann wird beim Speichern des Produktes jedesmal der Cache nach Tags durchsucht und gelöscht. 

Bie jedem Speichervorgang werden folgende Tags gelöscht:

  • <prefix>_CATALOG_PRODUCT
  • <prefix>_CATALOG_PRODUCT_
  • <prefix>_CATALOG_PRODUCT_<productId
  • <prefix>_CATALOG_CATEGORY_<categoryId> (für jede Kategorie)

Beim jedem Login ins Backend ist es folgendes Tag:

  • <prefix>_BACKEND_MAINMENU

Lösung:

Die Idee nun ist, alle Cache-Lösch-Anweisungen abzufangen und sie in eine Queue zu schreiben anstatt sie sofort auszuführen. Das erhöht die Geschwindigkeit beim Login und im Backend allgemein spürbar. Besonders beim Import von Produkten kann man das ständige Löschen des Caches so leicht umgehen, ohne den Cache generell ausschalten zu müssen.

Die Cache-Einträge in der Queue werden dann analysiert und neue Jobs extrahiert. Befindet sich in der Queue zum Beispiel eine "all" Anweisung, muss der Cache weder vorher noch nachher mühsam nach Tags durchsucht werden. Mehrere "matchingAnyTag" Anweisungen können zusammengefasst weden und mehrfache "old" oder "matchingTag" (mit gleichen Tag-Kombinationen) können vermieden werden.

Die neuen Jobs werden nun von einem Cronjob alle 15 Minuten im Hintergrund ausgeführt.

Ich habe dazu eine kleine Extension geschrieben (Alpha-Status):

Aoe_AsyncCache (GitHub)

(Einfach im Hauptverzeichnis entpacken oder Module-Manager verwenden. Modman-Konfigurationsdatei liegt bei.)

Extension auf GitHub: Aoe_AsyncCache

(Update auf 0.0.2: Kleinere Fehler beseitigt)

Diese Extension überscheibt die Klasse Varien_Cache_Core und beeinflusst dort die clean() Methode. Da diese Klasse innerhalb von Magento direkt instanziert wird, kann sie leider nicht über einen Rewrite sauber erweitert werden. Daher habe verwende ich hier eine lokale Kopie der Datei.

Die Extension erweitert außerdem Magentos "Cache Management" Modul um einen weiteren Abschnitt, der es erlaubt zu sehen, was sich gerade in der Queue befindet. Einzelne Queue-Einträge können dort gelöscht werden. Außerdem ist dort zu sehen, wie die komprimierte Job-Liste aussieht. Und schließlich kann das Abarbeiten der asynchronen Jobs dort auch manuell gestartet werden, falls man doch keine 15 Minuten bis zum nächsten Cronjob warten will.

Viel Spaß beim Ausprobieren. Feedback jeder Art ist wie immer sehr willkommen...

 

Recent Comments

Zend Certified Engineer (ZCE)
TYPO3 Certified Integrator
Magento Certified Developer PLUS