Full Page Cache: Tag-Invalidierung in Magento verstehen
AI generated
SET
TTL
Redis · Magento · Performance · Caching
Full Page Cache: Tag-Invalidierung in Magento verstehen
cache:clean, cache:flush und X-Magento-Tags im Detail

Eine funktionierende Tag-Invalidierung ist die Grundvoraussetzung dafuer, dass der Magento Full Page Cache ueberhaupt nutzbar bleibt, ohne veraltete Preise oder Lagerbestaende auszuliefern. Wer versteht, wie X-Magento-Tags gesetzt werden, wie Redis diese Tags intern verwaltet und warum cache:clean etwas grundlegend anderes tut als cache:flush, kann Invalidierungsprobleme gezielt statt durch pauschales Cache-Leeren loesen.

15 Min. Lesezeit X-Magento-Tags · cache:clean · cache:flush · Debugging Redis 7.x · Magento 2.4.8 · PHP 8.4

1. Wie der Magento Full Page Cache funktioniert

Der Full Page Cache (FPC) speichert die vollstaendig gerenderte HTML-Ausgabe einer Seite, sodass nachfolgende Requests direkt aus dem Cache bedient werden koennen, ohne Layout, Bloecke und Datenbankabfragen erneut auszufuehren. Fuer statische, seltene Aenderungen unterliegende Seiten wie CMS-Seiten oder Kategorieuebersichten bringt das massive Geschwindigkeitsgewinne. Das Problem: Eine Produktseite, die im Cache liegt, darf nicht ewig gueltig bleiben, sobald sich Preis, Lagerbestand oder Inhalt aendern, sonst zeigt der Shop veraltete Informationen.

Genau hier kommt die Tag-Invalidierung ins Spiel. Statt den kompletten FPC bei jeder Aenderung zu leeren, was die Vorteile des Caches zunichtemachen wuerde, markiert Magento jede gecachte Seite mit einer Reihe von Tags, die beschreiben, von welchen Entitaeten die Seite abhaengt. Aendert sich eine dieser Entitaeten, loest Magento eine gezielte Invalidierung genau dieser Seiten aus, waehrend alle anderen Cache-Eintraege unberuehrt bleiben.

Mit Redis als Full-Page-Cache-Backend erfolgt diese Tag-Invalidierung ueber dieselbe Cm_Cache_Backend_Redis-Klasse, die auch fuer den regulaeren Cache genutzt wird, allerdings typischerweise mit einem eigenen Datenbank-Index. Das Zusammenspiel aus HTTP-Response-Headern, Redis-Sets und Magentos Cache-Observer-Events bildet die technische Grundlage, die im Rest dieses Artikels Schritt fuer Schritt erklaert wird.

2. Cache-Tags: Konzept und Zweck der Tag-Invalidierung

Ein Cache-Tag ist ein String, der eine Beziehung zwischen einem Cache-Eintrag und einer Geschaeftsentitaet ausdrueckt, etwa cat_p_123 fuer Produkt-ID 123 oder cat_c_45 fuer Kategorie-ID 45. Jede gecachte Seite kann mehrere Tags tragen: Eine Produktseite traegt typischerweise das Produkt-Tag, Tags fuer alle zugeordneten Kategorien und ein generisches FPC-Tag. Diese Kombination stellt sicher, dass sowohl produktspezifische als auch kategoriebezogene Aenderungen die richtigen Seiten treffen.

Die Tag-Invalidierung wird durch Magentos Indexer- und Observer-System ausgeloest. Speichert ein Admin ein Produkt, feuert ein Event, das ueber Magento\Framework\App\CacheInterface::clean() mit dem Modus MATCHING_TAG genau die betroffenen Cache-Eintraege entfernt. Der entscheidende Vorteil gegenueber einer zeitbasierten Ablaufsteuerung: Seiten bleiben so lange im Cache, wie sich nichts an ihren Daten aendert, koennen aber sofort reagieren, sobald eine relevante Aenderung passiert.

3. Wie Tags in Redis gespeichert werden

Intern nutzt das Redis-Backend fuer die Tag-Invalidierung Sets: Fuer jedes Tag existiert ein Redis-Set unter dem Schluesselmuster zc:ta:TAG_NAME, das die IDs aller Cache-Eintraege enthaelt, die mit diesem Tag verknuepft sind. Beim Speichern einer Seite mit mehreren Tags fuegt Magento die Cache-ID in jedes der zugehoerigen Tag-Sets ein. Beim Aufruf von clean(MATCHING_TAG, ['cat_p_123']) liest Redis das entsprechende Set aus und loescht jeden darin enthaltenen Cache-Eintrag einzeln.

Diese Set-basierte Struktur ist der Grund, warum die Tag-Invalidierung in Redis so viel schneller ist als bei einem dateibasierten Cache mit Verzeichnis-Scans: Die Suche nach betroffenen Eintraegen erfolgt ueber einen direkten Set-Lookup mit konstanter bis linearer Komplexitaet zur Anzahl der Tag-Mitglieder, statt ueber ein vollstaendiges Durchsuchen aller Cache-Dateien. Bei grossen Katalogen mit hunderttausenden Produkten macht dieser Unterschied den entscheidenden Performance-Faktor aus.


# Inspect Full-Page-Cache tag sets directly in Redis (database index for page_cache)
redis-cli -n 1 SMEMBERS "zc:ta:cat_p_123"
redis-cli -n 1 SCARD "zc:ta:cat_p_123"

# List all cache entries associated with a category tag
redis-cli -n 1 SMEMBERS "zc:ta:cat_c_45"

# Check whether a specific cache entry still exists after invalidation
redis-cli -n 1 EXISTS "zc:k:CACHE_ID_HERE"

4. cache:clean vs cache:flush: der entscheidende Unterschied

bin/magento cache:clean loescht ausschliesslich Cache-Eintraege, die als ungueltig markiert sind, oder mit einem angegebenen Tag-Filter genau die passenden Eintraege. Das ist die feingranulare Variante der Tag-Invalidierung und entspricht exakt dem, was Magento auch automatisch bei einer Produktaenderung ausloest. Nach cache:clean bleiben alle nicht betroffenen Cache-Eintraege vollstaendig erhalten.

bin/magento cache:flush hingegen leert den kompletten Cache-Speicher der angegebenen Cache-Typen bedingungslos, unabhaengig von Tags. Bei Redis als Backend entspricht das im Kern einem FLUSHDB auf die betroffene Datenbank. Der Unterschied ist fundamental: cache:flush ist ein Reset-Kommando, waehrend cache:clean die praezise Tag-Invalidierung darstellt, auf die sich der Produktionsbetrieb verlassen sollte. Wer routinemaessig cache:flush statt cache:clean nutzt, verschenkt den gesamten Performance-Vorteil des Full Page Cache bei jeder Bereinigung.


# Targeted cleanup: removes only entries matching the given tags (fast, safe)
bin/magento cache:clean full_page

# Full reset: unconditionally clears the entire cache database (use sparingly)
bin/magento cache:flush full_page

# Clean by explicit tag via the Redis CLI, mirroring what Magento does internally
redis-cli -n 1 SMEMBERS "zc:ta:cat_p_123" | xargs -I{} redis-cli -n 1 DEL "zc:k:{}"

# Verify how many keys remain in the full page cache database afterward
redis-cli -n 1 DBSIZE

Wenn Varnish oder ein aehnlicher HTTP-Reverse-Proxy vor Magento sitzt, kommuniziert Magento die relevanten Tags einer Response ueber den HTTP-Header X-Magento-Tags. Varnish liest diesen Header beim Ausliefern einer Seite und speichert intern eine eigene Zuordnung von Tags zu gecachten Objekten, unabhaengig vom Redis-Backend. Bei einer Aenderung sendet Magento einen HTTP PURGE-Request mit denselben Tags an Varnish, das daraufhin seine eigenen Ban-Regeln anwendet.

Wichtig zu verstehen: Ohne Varnish arbeitet die Tag-Invalidierung ausschliesslich innerhalb von Redis ueber die im vorherigen Abschnitt beschriebenen Sets, der X-Magento-Tags-Header hat dann keine praktische Wirkung mehr. Mit Varnish existieren zwei parallele Invalidierungsmechanismen: einer in Redis fuer den eigentlichen Full-Page-Cache-Speicher und einer in Varnish fuer den vorgelagerten HTTP-Cache. Beide muessen synchron funktionieren, sonst entstehen Situationen, in denen Varnish eine veraltete Seite ausliefert, obwohl der Redis-Cache bereits korrekt invalidiert wurde.


# Inspect the X-Magento-Tags header on a response (only meaningful with Varnish upstream)
curl -sI https://shop.example.com/product-page.html | grep -i "x-magento-tags"

# Confirm cache origin: HIT means a cached version was served
curl -sI https://shop.example.com/product-page.html | grep -i "x-magento-cache-debug"

6. Debugging: warum eine Seite nicht invalidiert wurde

Der haeufigste Support-Fall bei der Tag-Invalidierung: Ein Produkt wurde geaendert, aber die Frontend-Seite zeigt weiterhin alte Daten. Der erste Debugging-Schritt ist, mit den Browser-Entwicklertools den HTTP-Header X-Magento-Cache-Debug zu pruefen, der HIT oder MISS anzeigt. Bei HIT wird tatsaechlich eine gecachte Version ausgeliefert, was bestaetigt, dass die Invalidierung fehlgeschlagen ist, statt dass es sich um ein unabhaengiges Datenproblem handelt.

Der zweite Schritt ist, direkt in Redis zu pruefen, ob das erwartete Tag ueberhaupt existiert und ob der betroffene Cache-Eintrag noch im entsprechenden Tag-Set gelistet ist. Fehlt das Tag im Set, obwohl die Seite urspruenglich mit diesem Tag gespeichert wurde, deutet das auf ein Problem beim Setzen der Tags hin, meist verursacht durch einen Custom Block, der getCacheKeyInfo() nicht korrekt implementiert oder die relevanten Tags nicht an getIdentities() weiterreicht.


<?php
declare(strict_types=1);

namespace Mironsoft\Catalog\Block;

use Magento\Catalog\Block\Product\View as ProductView;

/**
 * Example block that must correctly expose cache identities
 * so tag-based invalidation can find and clear it.
 */
class CustomProductBlock extends ProductView
{
    /**
     * Returns cache identities used by Magento's tag-based invalidation.
     *
     * @return string[]
     */
    public function getIdentities(): array
    {
        $product = $this->getProduct();

        // Missing this merge is the most common cause of stale FPC pages
        return array_merge(
            parent::getIdentities(),
            $product ? [\Magento\Catalog\Model\Product::CACHE_TAG . '_' . $product->getId()] : []
        );
    }
}

7. Haeufige Ursachen fuer fehlerhafte Invalidierung

Die mit Abstand haeufigste Ursache fehlerhafter Tag-Invalidierung ist ein Custom Block oder ein Plugin, das getIdentities() ueberschreibt, dabei aber vergisst, parent::getIdentities() per array_merge einzubinden. Dadurch verliert der Block alle Standard-Tags, die Magento normalerweise setzt, und die Seite wird bei regulaeren Produktaenderungen nicht mehr invalidiert, obwohl sie im Cache liegt.

Eine zweite haeufige Ursache ist asynchrone Verarbeitung ueber Message Queues: Wenn Produktaktualisierungen ueber async.operations.all verarbeitet werden, findet die eigentliche Tag-Invalidierung erst statt, wenn der Consumer die Nachricht abgearbeitet hat. Laeuft der Consumer nicht oder ist er im Rueckstand, bleibt der Cache trotz gespeicherter Aenderung unveraendert. Ein dritter Fall betrifft Drittanbieter-Module, die eigene, nicht-standardkonforme Caching-Strategien implementieren und dabei die Tag-Konventionen des Kernsystems ignorieren.

8. redis-cli Befehle zur Tag-Analyse

Fuer die systematische Analyse der Tag-Invalidierung in der Produktion sind wenige redis-cli-Befehle ausreichend. SMEMBERS zeigt die Mitglieder eines Tag-Sets, SCARD liefert nur die Anzahl, was bei sehr grossen Sets performanter ist, um vorab abzuschaetzen, wie umfangreich eine Invalidierung sein wird. TTL auf einen Cache-Key zeigt, ob ein Eintrag ueberhaupt noch aktiv ist oder bereits durch normale TTL-basierte Ablaufsteuerung entfernt wurde.

Fuer tiefere Analyse hilft redis-cli --scan --pattern "zc:ta:cat_p_*", um alle produktbezogenen Tag-Sets zu finden, ohne den blockierenden KEYS-Befehl in der Produktion einzusetzen. SCAN iteriert inkrementell und cursor-basiert, was bei einer grossen Anzahl Schluesseln entscheidend ist, um den Redis-Server nicht durch einen einzelnen, lang blockierenden Befehl auszubremsen.


# Safe, non-blocking way to find product-related tag sets in production
redis-cli --scan --pattern "zc:ta:cat_p_*" | head -20

# Count members of a specific tag set without loading all of them
redis-cli SCARD "zc:ta:cat_p_123"

# Check whether a cache entry has already expired via TTL
redis-cli TTL "zc:k:CACHE_ID_HERE"

9. clean vs flush vs Varnish-Ban im Vergleich

Je nach Situation ist eine andere Invalidierungsmethode angemessen. Die folgende Tabelle ordnet die Optionen nach Praezision und Einsatzzweck.

Methode Umfang Performance-Impact Einsatzzweck
cache:clean (Tag) Nur betroffene Eintraege Minimal, Cache bleibt groesstenteils warm Automatische Invalidierung im Regelbetrieb
cache:flush Kompletter Cache-Typ Hoch, komplette Neuberechnung noetig Nur nach Deployments oder Notfaellen
Varnish PURGE/Ban Nur betroffene Seiten in Varnish Minimal, wirkt zusaetzlich zu Redis Wenn Varnish vorgeschaltet ist
Manuelles FLUSHDB Gesamte Redis-Datenbank Sehr hoch, betrifft auch andere Rollen bei falscher DB-Trennung Nur im absoluten Ausnahmefall

In der Praxis sollte cache:clean mit Tag-Filter die absolute Regel sein, waehrend cache:flush auf seltene Faelle wie grosse Deployments oder inkonsistente Cache-Zustaende beschraenkt bleibt. Wer regelmaessig zu cache:flush greift, weil die Tag-Invalidierung nicht zuverlaessig funktioniert, sollte die Ursache im Custom Code suchen statt das Symptom mit einem vollstaendigen Reset zu ueberdecken.

10. Zusammenfassung

Die Tag-Invalidierung ist das Herzstueck eines funktionierenden Full Page Cache: Sie erlaubt es, Seiten lange im Cache zu halten und trotzdem sofort auf relevante Datenaenderungen zu reagieren. In Redis wird das ueber Tag-Sets mit dem Praefix zc:ta: realisiert, die eine effiziente, gezielte Loeschung betroffener Eintraege ermoeglichen, ohne den gesamten Cache zu leeren.

Der Unterschied zwischen cache:clean und cache:flush ist entscheidend fuer den Produktionsbetrieb: Ersteres ist die praezise Tag-Invalidierung, letzteres ein bedingungsloser Reset. Wer Invalidierungsprobleme debuggt, sollte zuerst den X-Magento-Cache-Debug-Header pruefen, dann direkt in Redis nachsehen, ob das erwartete Tag im richtigen Set steht, und schliesslich Custom Blocks auf korrekt implementierte getIdentities()-Methoden pruefen.

Tag-Invalidierung im Magento Full Page Cache - Das Wichtigste auf einen Blick

Tag-Sets in Redis

Praefix zc:ta:TAG_NAME speichert alle Cache-IDs, die mit einem Tag verknuepft sind.

clean statt flush

cache:clean ist die praezise Invalidierung, cache:flush ein bedingungsloser Reset. Im Regelbetrieb immer clean nutzen.

getIdentities() pruefen

Custom Blocks muessen parent::getIdentities() einbinden, sonst gehen Standard-Tags verloren.

Debugging-Header nutzen

X-Magento-Cache-Debug zeigt HIT oder MISS und ist der erste Schritt jeder Fehlersuche.

11. FAQ: Tag-Invalidierung im Magento Full Page Cache

1Unterschied cache:clean vs cache:flush?
clean loescht gezielt passende Eintraege, flush leert alles bedingungslos. Fuer Regelbetrieb immer clean nutzen.
2Wie speichert Redis Cache-Tags?
Als Sets unter zc:ta:TAG_NAME mit den IDs aller verknuepften Cache-Eintraege.
3Warum wird eine Produktseite nicht invalidiert?
Meist fehlendes parent::getIdentities() in einem Custom Block, wodurch Standard-Tags verloren gehen.
4Was bewirkt X-Magento-Tags?
Kommuniziert Varnish relevante Tags. Ohne Varnish laeuft die Invalidierung nur ueber Redis-Sets.
5Cache-Herkunft einer Seite pruefen?
X-Magento-Cache-Debug Header zeigt HIT oder MISS, erster Debugging-Schritt.
6Warum nicht routinemaessig flush nutzen?
Zerstoert auch unbetroffene warme Eintraege, erzeugt unnoetige Last durch Neuberechnung.
7Rolle von Message Queues?
Bei async.operations.all findet Invalidierung erst nach Consumer-Verarbeitung statt. Verzoegerter Consumer verzoegert die Invalidierung.
8Cache-Eintraege zu einem Tag finden?
redis-cli SMEMBERS zc:ta:TAG_NAME, SCARD fuer nur die Anzahl bei grossen Sets.
9KEYS oder SCAN in Produktion?
Immer SCAN, cursor-basiert und nicht blockierend. KEYS in Produktion vermeiden.
10Redis-Invalidierung vs Varnish-Ban?
Zwei unabhaengige, parallele Mechanismen: Redis fuer den FPC-Speicher, Varnish fuer den vorgeschalteten HTTP-Cache.