Ein Cache kann Antwortzeiten und die Last auf Datenbanken oder externen Diensten reduzieren. Er behebt jedoch weder ineffiziente Abfragen noch eine Architektur mit unscharf definierten Grenzen. Eine Cache-Strategie in PHP muss festlegen, was gespeichert wird, wer es erhalten darf, wie lange es gültig ist und was geschieht, wenn der Speichermechanismus ausfällt.
Der Erfolg bemisst sich nicht allein an einer höheren Trefferquote. Die Anwendung muss ihre Geschäftsregeln auch dann einhalten, wenn der Cache leer, veraltet oder nicht verfügbar ist. Dafür empfiehlt es sich, zunächst das Problem zu messen und den Cache als Optimierung mit überprüfbarem Verhalten zu behandeln – nicht als primäre Quelle der Wahrheit.
Messen, bevor Sie entscheiden, was gespeichert wird

Ermitteln Sie zunächst langsame Routen und deren Ursachen. Erfassen Sie Antwortzeiten pro Endpunkt, Abfragelatenzen, Aufrufe externer Dienste, CPU-Auslastung und Anfragevolumen. Betrachten Sie neben Durchschnittswerten auch hohe Perzentile: Ein akzeptabler Durchschnitt kann sehr langsame Antworten für einen Teil der Nutzer verbergen.
Suchen Sie nach wiederholten Vorgängen, deren Ergebnis sich seltener ändert, als es angefordert wird: Kataloge, öffentliche Konfiguration, veröffentlichte Inhalte oder aufwendige Aggregationen. Prüfen Sie außerdem, ob die Langsamkeit auf Abfragen ohne Indizes, zu viele Anfragen, Serialisierung oder wiederholte Arbeit innerhalb derselben Anfrage zurückzuführen ist. Es kann sinnvoller sein, die Abfrage zu verbessern, als ein Ergebnis zu speichern, das sich nur schwer invalidieren lässt.
Legen Sie vor der Änderung einen Referenzwert fest: für Leistung, Last und beobachtete Datenqualität. Vergleichen Sie anschließend denselben Datenverkehr oder einen reproduzierbaren Test. Lässt sich die Verbesserung nicht dem Cache zuordnen, sind seine Betriebskosten und Nebenwirkungen nur schwer zu bewerten.
Zwischen Anwendungs-, HTTP- und Abfrage-Cache wählen
Ein Anwendungscache speichert Werte, die PHP-Code wiederverwenden kann, etwa Abfrageergebnisse oder berechnete Antworten. Er kann sich in gemeinsam genutztem Speicher, einem dedizierten Dienst oder einem anderen mit der Anwendung kompatiblen Backend befinden. Er eignet sich, wenn mehrere Anfragen dasselbe Ergebnis benötigen und sich dessen Geltungsbereich und Gültigkeitsdauer genau festlegen lassen.
Ein HTTP-Cache verwendet Direktiven wie Cache-Control, ETag und Validatoren, damit Browser oder Zwischenstationen Antworten wiederverwenden können. Das ist nützlich für öffentliche Ressourcen oder Antworten, deren Datenschutzrichtlinie eine Speicherung erlaubt. Bei personalisierten Antworten ist besondere Vorsicht geboten: Eine öffentliche Richtlinie kann Daten offenlegen, während eine private oder nicht speicherbare Richtlinie diese Möglichkeit verringern kann – abhängig vom Ablauf und den beteiligten Zwischenstationen.
Ein Abfrage-Cache kann eine Funktion der Datenbank, des Treibers oder einer ergebnisspeichernden Schicht sein. Er ist nicht mit der Optimierung des Datenzugriffs gleichzusetzen: Ein Cache ersetzt weder Indizes noch geeignete Abfragepläne oder Transaktionen. Machen Sie sich vor der Aktivierung damit vertraut, wer Einträge invalidiert und ob Lesezugriffe Schreibvorgänge sofort widerspiegeln müssen.
Wählen Sie die Ebene, die dem Problem am nächsten liegt, und nicht alle Ebenen gleichzeitig. Werden Caches ohne ein explizites Modell übereinandergestapelt, können verschiedene Ebenen unterschiedliche Versionen derselben Daten vorhalten und die Diagnose erschweren.
Schlüssel, Geltungsbereich und Ablaufzeit entwerfen
Ein Schlüssel muss alle Faktoren identifizieren, die das Ergebnis verändern. Eine Katalogantwort kann beispielsweise von Sprache, Währung, Region und Datenversion abhängen. Nehmen Sie diese Elemente stabil und nachvollziehbar auf, um die Diagnose zu erleichtern; vermeiden Sie es, vertrauliche Informationen im Schlüssel zu speichern.
Hängt das Ergebnis vom Nutzer, von dessen Rolle oder Berechtigungen oder von der Organisation ab, muss sich diese Trennung im Schlüssel widerspiegeln. Ein Schlüssel, der nur den Routennamen enthält, kann dazu führen, dass eine personalisierte Antwort eine andere Person erreicht. Prüfen Sie auch, wie Einträge über Prozesse und Server hinweg gemeinsam genutzt werden. Können Sie nicht alle Dimensionen, die das Ergebnis beeinflussen, zuverlässig aufzählen, sollten Sie diese Antwort nicht gemeinsam speichern.
Die Ablaufzeit sollte sich aus einer Geschäftsregel ergeben und nicht willkürlich gewählt werden. Eine Konfiguration, die sich nur selten ändert, verträgt möglicherweise ein längeres Zeitfenster als der Kontostand oder der Status einer Reservierung. Legen Sie fest, wie lange Daten höchstens veraltet sein dürfen, und erwägen Sie zufällige Abweichungen bei Ablaufzeiten, wenn viele ähnliche Einträge gleichzeitig ablaufen könnten.
Der zeitbasierte Ablauf ersetzt nicht die Invalidierung bei wichtigen Änderungen. Er bildet eine letzte Grenze, damit ein Eintrag nicht unbegrenzt bestehen bleibt, ist aber keine Garantie für eine sofortige Aktualisierung.
Aktualisieren und invalidieren, wenn sich die Quelle ändert
Wählen Sie einen Mechanismus, der dem erforderlichen Maß an Konsistenz entspricht. Eine explizite Invalidierung kann nach einem Schreibvorgang erfolgen. Das ist unkompliziert, kann aber fehlschlagen, wenn der Prozess zwischen dem Speichern der Daten und dem Löschen des Cache-Eintrags unterbrochen wird. Eine Alternative sind Versionen in den Schlüsseln: Ändert sich die Quelle, wird die Version erhöht und auf frühere Einträge nicht mehr zugegriffen. Dafür muss diese Version korrekt verwaltet werden.
In ereignisgesteuerten Systemen kann eine bestätigte Änderung eine Benachrichtigung auslösen, um abgeleitete Daten zu invalidieren oder neu zu berechnen. Ist die Zustellung von Ereignissen nicht zuverlässig, sollten Sie Wiederholungsversuche, Idempotenz und einen Abgleichsmechanismus vorsehen. Gehen Sie nicht davon aus, dass die Aktualisierung der Datenbank und des Cache-Dienstes einen atomaren Vorgang bildet.
Bei Daten, die eine kurze Veraltung tolerieren, kann es sinnvoll sein, einen abgelaufenen Eintrag auszuliefern, während er im Hintergrund aktualisiert wird. Diese Technik eignet sich nicht für alle Informationen: Legen Sie fest, welche Daten dafür infrage kommen, wie lange sie zusätzlich veraltet sein dürfen und was bei einem fehlgeschlagenen Update geschieht. Maßgeblich für die Entscheidung sollten die Auswirkungen sein, die das Anzeigen eines älteren Werts hat.
Ein sicheres Verhalten bei Ausfällen festlegen
Testen Sie drei unterschiedliche Zustände: keinen Eintrag, einen abgelaufenen Eintrag und ein nicht verfügbares Backend. Entscheiden Sie für jeden Zustand, ob die Anwendung die Daten aus der Quelle neu berechnet, kontrolliert mit einem Fehler antwortet oder – sofern sicher – einen älteren Wert ausliefert. Ein leerer Cache muss ein normaler Ausgangszustand sein und darf keine falschen Ergebnisse verursachen.
Schützen Sie die Quelle vor einem Ausfall des Backends. Löst jede Anfrage beim Ablauf desselben Schlüssels eine kostspielige Abfrage aus, kann eine Lastspitze entstehen. Mögliche Maßnahmen sind, die Zahl gleichzeitiger Neuberechnungen zu begrenzen, vorübergehend sichere Werte wiederzuverwenden oder Grenzwerte und Zeitlimits anzuwenden. Welche Lösung geeignet ist, hängt davon ab, ob veraltete Daten ausgeliefert werden dürfen und welche Kapazität die Quelle hat.
Protokollieren Sie Fehler, Latenzen sowie fehlgeschlagene Lese- und Schreibzugriffe, ohne private Werte aufzunehmen. Ein Cache ist in der Regel eine Abhängigkeit für die Leistung und keine Datenautorität. Muss seine Nichtverfügbarkeit einen kritischen Vorgang stoppen, ist diese Entscheidung ausdrücklich zu begründen.
Konsistenz und Leistung mit reproduzierbaren Tests validieren
Vergleichen Sie Szenarien mit deaktiviertem, kaltem und warmem Cache. Berücksichtigen Sie die erste Anfrage nach einem Schreibvorgang, Änderungen an Sprache oder Berechtigungen, gleichzeitigen Ablauf und einen Backend-Ausfall. Prüfen Sie sowohl den Inhalt als auch die Trennung: Nutzer mit unterschiedlichen Berechtigungen dürfen keine Antworten füreinander erhalten.
Verwenden Sie automatisierte Tests für wichtige Regeln zu Schlüsseln und Invalidierung sowie Integrationstests, um das Verhalten mit dem echten Backend oder einer repräsentativen Alternative zu prüfen. Beobachten Sie unter Last Treffer und Fehlschläge, Cache-Latenz, Neuberechnungsvorgänge, Last auf der Quelle und Fehler. Eine hohe Trefferquote beweist nicht, dass die Antworten korrekt sind.
Vergleichen Sie bei der Bereitstellung einer Änderung die Metriken und Fehler mit einem Referenzwert. Halten Sie eine Möglichkeit bereit, die Optimierung zu deaktivieren oder auf ein sicheres Verhalten zurückzugehen, falls veraltete Daten, steigender Speicherverbrauch oder unerwarteter Druck auf die Datenbank auftreten.
Checkliste für den Cache-Betrieb

- Problem gemessen: Die Routen und Vorgänge, die den Cache-Einsatz rechtfertigen, sind bekannt.
- Gecachte Daten und Quelle definiert: Der Cache wird nicht als primäre Datenquelle behandelt.
- Vollständiger Schlüssel: Er enthält die relevanten fachlichen Dimensionen und Berechtigungen.
- Ablaufzeit begründet: Sie entspricht der geschäftlichen Toleranz gegenüber veralteten Daten.
- Invalidierung vorgesehen: Es ist festgelegt, welches Ereignis jeden Eintrag aktualisiert oder ersetzt.
- Ausfälle abgedeckt: Für einen leeren, abgelaufenen oder nicht verfügbaren Cache ist das Verhalten definiert.
- Betrieb überwacht: Latenz, Fehler, Treffer und Last auf der Quelle werden beobachtet.
- Trennung getestet: Nutzer, Rollen, Sprachen und andere relevante Kontexte werden validiert.
Eine solide Cache-Strategie reduziert wiederholte Arbeit, ohne die Bedeutung der Daten unbeabsichtigt zu verändern. Hat jeder Eintrag einen klaren Geltungsbereich, eine Gültigkeitsrichtlinie und einen überprüfbaren Ausfallplan, kann das Team seinen Nutzen bewerten und die Optimierung anpassen oder entfernen, wenn sie nicht mehr geeignet ist.



