Write Through Cache
In Cache und Datenbank zugleich schreiben
Die Idee und ihr Nutzen
Die Kontaktadressen der Kunden einer Versicherung werden sehr oft gelesen, etwa bei jedem Öffnen einer Schadenakte. Die Sachbearbeiter arbeiten mit einer Anwendung, die die Adressen zusätzlich in einem Cache hält, einem Zwischenspeicher im Arbeitsspeicher. So muss die Anwendung nicht bei jedem Lesen die Datenbank abfragen. Ändert die Sachbearbeiterin Mara die Adresse von Kunde 4711, geht die Änderung an den Cache-Baustein, den Programmteil, der den Cache verwaltet. Der Cache-Baustein gibt die Änderung sofort an die Datenbank weiter, die die Adresse dauerhaft speichert. Erst wenn die Datenbank das Speichern bestätigt hat, gleicht der Cache-Baustein den Cache an. Danach meldet die Anwendung Mara, dass die Änderung gespeichert ist, und jede Leseanfrage erhält aus dem Cache die neue Adresse. Dieses Vorgehen heißt Write Through, auf Deutsch Durchschreiben. Der Name meint: Jede Änderung geht durch den Cache-Baustein hindurch sofort bis in die Datenbank.
Wie funktioniert es?
Mara ändert die Adresse von Kunde 4711 vom Birkenweg 3 in die Eichenstraße 12. Die Anwendung schickt den Schreibauftrag an den Cache-Baustein, der alle Adressänderungen entgegennimmt. Der Cache-Baustein gibt die Änderung sofort an die Datenbank weiter und wartet auf die Antwort der Datenbank. Die Datenbank speichert die Eichenstraße 12 dauerhaft und meldet „gespeichert“. Erst jetzt trägt der Cache-Baustein die Eichenstraße 12 in den Cache ein, und erst danach meldet die Anwendung Mara „Adresse gespeichert“. Eine Minute später öffnet ein Kollege von Mara die Akte von Kunde 4711. Die Anwendung liest die Adresse aus dem Cache, und der Kollege sieht die Eichenstraße 12. Später gibt Mara bei einer anderen Adressänderung eine ungültige Postleitzahl ein. Der Cache-Baustein versucht, die Änderung zu speichern, und die Datenbank lehnt sie ab. Der Cache-Baustein darf den abgelehnten Wert nicht anbieten. Hätte er den Wert vorab schon in den Cache eingetragen, müsste er ihn wieder entfernen. Mara erhält eine Fehlermeldung statt einer Erfolgsmeldung.
Der Cache-Baustein verwaltet den Cache und ist zugleich der einzige Zugang der Anwendung zum Schreiben von Adressen. Leseanfragen beantwortet der Cache-Baustein aus dem Cache. Die Datenbank ist der verbindliche Stand der Adressen, der Cache hält nur eine schnell lesbare Kopie davon. Den Eintrag im Cache kann der Cache-Baustein auf zwei Arten angleichen: Er trägt den neuen Wert in den Cache ein, oder er löscht den alten Eintrag, sodass die nächste Leseanfrage den neuen Wert frisch aus der Datenbank holt. Write Through garantiert nicht, dass Cache und Datenbank in jedem Moment übereinstimmen. Cache und Datenbank bilden keine gemeinsame Transaktion, also keinen Vorgang, der in beiden Speichern nur ganz oder gar nicht gelingt. Das Schreiben in die Datenbank und das Angleichen des Caches können deshalb getrennt gelingen oder scheitern.
Scheitert nur das Angleichen des Caches, nachdem die Datenbank bereits gespeichert hat, muss der Cache-Baustein den alten Eintrag im Cache löschen oder später angleichen. Erhält der Cache-Baustein von der Datenbank gar keine Antwort, etwa weil die Wartezeit abgelaufen ist, weiß er nicht, ob die Adresse gespeichert wurde. Er darf dann weder Erfolg melden noch den neuen Wert anbieten. In diesem Fall löscht der Cache-Baustein am besten den Cache-Eintrag, sodass die nächste Leseanfrage den tatsächlich gespeicherten Stand aus der Datenbank holt. Manche Programme ändern Adressen direkt in der Datenbank. Ein Beispiel ist ein nächtlicher Abgleich mit dem Einwohnermeldeamt. Von solchen Änderungen weiß der Cache-Baustein nichts. Für diesen Fall braucht die Anwendung eine zusätzliche Regel, etwa dass das ändernde Programm die betroffenen Cache-Einträge löscht.
Write-Through Cache: erst die Datenbank, dann der Cache, dann die Erfolgsmeldung
Wann ist es sinnvoll und wann nicht?
Ein Write Through Cache lohnt sich
- Daten werden viel häufiger gelesen als geändert. Ein Beispiel sind die Kundenadressen. Ohne Cache fragt die Anwendung bei jedem Öffnen einer Schadenakte die Datenbank nach der Adresse. Mit Write Through liest die Anwendung die Adressen aus dem Cache, und nur die seltenen Adressänderungen warten auf die Datenbank.
- Nach einer Änderung muss die nächste Leseanfrage sofort den neuen Wert erhalten. Ändert jemand eine Adresse nur in der Datenbank, steht im Cache weiterhin die alte Adresse. Die Anwendung zeigt dann trotz erfolgreicher Änderung den alten Wert an, und Briefe gehen womöglich an die frühere Anschrift.
- Alle Adressänderungen gehen an denselben Cache-Baustein, der sie an die Datenbank weitergibt. Nur dann erfährt der Cache-Baustein von jeder geänderten Adresse und kann den Cache angleichen.
Ein Write Through Cache ist nicht das Richtige
- Daten werden sehr oft geändert, aber selten gelesen. Write Through würde dann jede Änderung zusätzlich in den Cache schreiben, aus dem kaum jemand liest. Stattdessen schreibt und liest die Anwendung direkt in der Datenbank. Der Cache, der Arbeitsspeicher belegt und betrieben werden muss, entfällt, und keine Änderung muss zusätzlich in den Cache geschrieben werden.
- Adressen werden nach einer Änderung selten sofort wieder gelesen. Dann schreibt die Anwendung die Änderung nur in die Datenbank und löscht den Cache-Eintrag; das heißt Cache Aside. Die nächste Leseanfrage holt den neuen Wert aus der Datenbank. Adressen, die nach einer Änderung niemand liest, belegen dann keinen Platz im Cache.
- Andere Programme schreiben direkt in die Datenbank, ohne den Cache-Baustein, etwa der nächtliche Abgleich mit dem Einwohnermeldeamt, und keine Regel löscht die veralteten Cache-Einträge. Write Through allein hält den Cache dann nicht aktuell. Das Entwicklungsteam legt dann zuerst fest, dass jedes ändernde Programm die betroffenen Cache-Einträge löscht. Ohne diese Regel liefert der Cache veraltete Adressen, obwohl die Anwendung selbst über den Cache-Baustein schreibt.
- Jede Änderung muss so schnell wie möglich bestätigt werden. Mit Write Through wartet Mara bei jeder Änderung, bis die Datenbank gespeichert hat. Ist ein kleines Risiko verlorener Änderungen hinnehmbar, setzt das Entwicklungsteam einen Write Behind Cache ein. Der Write Behind Cache bestätigt eine Änderung schon nach dem Eintrag im Cache und schreibt sie erst später in die Datenbank. Die Anwendung wartet dann nicht auf die Datenbank. Fällt der Cache vor dem Schreiben aus, gehen bestätigte Änderungen allerdings verloren.
Nachteile und typische Fehler
Jede Änderung dauert länger als ein reines Schreiben in die Datenbank, weil zusätzlich der Cache angeglichen wird. Die Regeln für Fehler zwischen dem Speichern in der Datenbank und dem Angleichen des Caches, für gleichzeitige Änderungen und für Änderungen am Cache vorbei muss die Anwendung zusätzlich enthalten. Der Cache muss neben der Datenbank betrieben werden und braucht so viel Arbeitsspeicher, dass die häufig gelesenen Adressen hineinpassen. Weil jede Änderung in den Cache geschrieben wird, landen dort auch Adressen, die danach kaum jemand liest. Eine Ablaufzeit, nach der ein Eintrag aus dem Cache gelöscht wird, hält den Cache klein.
Typische Fehler und woran man sie erkennt:
- Fehler zwischen den Schritten: Die Datenbank speichert die Eichenstraße 12, aber das Angleichen des Caches scheitert, und die Anwendung hat keine Regel zum Wiederholen oder Löschen. Der Cache liefert weiter den Birkenweg 3. Erkennbar ist das an Akten, die eine andere Adresse zeigen als die Datenbank.
- Gleichzeitige Änderungen: Zwei Personen ändern gleichzeitig dieselbe Adresse. Mara speichert die Eichenstraße 12, ein Kollege kurz danach die Lindenallee 5, und die Datenbank speichert beide Werte in dieser Reihenfolge. Die Bestätigung für Maras Änderung erreicht den Cache-Baustein aber erst nach der Bestätigung für den Kollegen. Der Cache-Baustein trägt deshalb zuerst die Lindenallee 5 und danach die Eichenstraße 12 in den Cache ein. Im Cache steht dann die Eichenstraße 12, in der Datenbank die Lindenallee 5. Erkennbar ist das an Abweichungen zwischen Cache und Datenbank, die genau bei Datensätzen mit mehreren Änderungen kurz hintereinander auftreten.
- Änderung am Cache vorbei: Der nächtliche Abgleich mit dem Einwohnermeldeamt ändert Adressen direkt in der Datenbank, und der Cache liefert am nächsten Morgen die alten Adressen. Erkennbar ist das an Adressen, die sich nach dem Neustart des Caches plötzlich ändern.
- Unbestätigter Wert im Cache: Der Cache-Baustein trägt die neue Adresse ein, bevor die Datenbank bestätigt, und entfernt sie nach einer Ablehnung nicht. Andere Sachbearbeiter sehen dann eine Adresse, die nie gespeichert wurde. Erkennbar ist das an Werten im Cache, die in der Datenbank nicht vorkommen.
- Leerer Cache nach Neustart: Nach einem Neustart ist der Cache leer, und die Anwendung liest fehlende Einträge nicht aus der Datenbank nach. Adressen erscheinen dann erst wieder, wenn sie jemand ändert. Erkennbar ist das an leeren Adressfeldern in Akten nach einem Neustart des Caches. Write Through lässt sich dafür mit Cache Aside verbinden: Beim Lesen lädt die Anwendung fehlende Einträge selbst aus der Datenbank.
Weiterführend
Verwandte Ansätze
- Caching: der allgemeine Ansatz, häufig gelesene Daten in einem Zwischenspeicher vorzuhalten.
- Optimistic Locking: erkennt, wenn zwei Personen gleichzeitig dieselbe Adresse ändern, und verhindert, dass eine Änderung die andere unbemerkt überschreibt.
- Change Data Capture: liest Änderungen direkt aus der Datenbank aus und kann so Cache-Einträge löschen, die ein nächtlicher Abgleich am Cache vorbei geändert hat.
Quellen
- Amazon ElastiCache: Caching strategies for Memcached: beschreibt Write Through mit seinen Vorteilen und Nachteilen, darunter die zusätzliche Zeit bei jedem Schreiben, fehlende Einträge in einem neuen, leeren Cache und das Zusammenspiel mit dem Nachladen fehlender Einträge beim Lesen und mit Ablaufzeiten.
- Microsoft: Caching guidance: vergleicht im Abschnitt zur Konsistenz beim Schreiben das Löschen des Cache-Eintrags mit Write Through und empfiehlt Write Through für viel gelesene Daten, die nach einer Änderung sofort aktuell sein müssen.