DynamoDB: stark vs. letztendlich konsistente Reads
Du aktualisierst ein Item, liest es sofort zurück und bekommst den alten Wert. Der Write war erfolgreich — einen Moment später liefert derselbe Read den neuen Wert. Nichts ist kaputt: Du bist auf DynamoDBs standardmäßig letztendlich konsistenten Read gestoßen, und du kannst ihn pro Request abwählen.
Das ist einer der wenigen Korrektheits-Regler, die DynamoDB dir direkt in die Hand gibt, und er hat einen echten Preis. Ihn richtig zu stellen heißt zu wissen, was jeder Modus garantiert, was er kostet und wo starke Reads schlicht nicht zur Verfügung stehen.
Was ist der Unterschied zwischen stark und letztendlich konsistenten Reads in DynamoDB?
Ein letztendlich konsistenter Read (die Vorgabe) wird von einem beliebigen Replikat bedient, kann direkt nach einem Write also kurz veraltete Daten liefern — kostet dafür aber nur die Hälfte. Ein stark konsistenter Read, den du pro Request mit ConsistentRead=true anforderst, geht an den Leader der Partition und spiegelt immer jeden committeten Write wider — zur doppelten Lesekapazität.
- Letztendlich konsistent (die Vorgabe) — kann direkt nach einem Write kurz veraltete Daten liefern. Der günstigste Lesemodus.
- Stark konsistent — spiegelt immer jeden Write wider, der vor dem Read committet wurde.
Pro Request mit
ConsistentRead=trueanfordern. - Starke Reads kosten das 2-Fache. Ein stark konsistenter Read verbraucht für dieselben Daten doppelt so viel Lesekapazität wie ein letztendlich konsistenter.
- Nicht überall. Starke Reads bekommst du auf der Basistabelle und auf einem Local Secondary Index. Ein Global Secondary Index kann nur letztendlich konsistent — kein Opt-in.
- Standardmäßig letztendlich konsistent lesen. Greif nur dann zu stark, wenn du deine eigenen gerade geschriebenen Daten liest und ein kurzer veralteter Stand falsch wäre.
Das Problem: ein Read, der den letzten Write nicht sieht
Sagen wir, du betreibst Benutzerkonten. Ein Nutzer ändert seine Benachrichtigungs-E-Mail, deine App schreibt das Update, und der Bestätigungsbildschirm liest das Profil sofort erneut, um die neue Adresse anzuzeigen. Im Standard-Lesemodus kann dieser erneute Read auf einem Replikat landen, das die Änderung noch nicht hat — der Nutzer sieht seine alte E-Mail und nimmt an, das Speichern sei fehlgeschlagen.
Das Fenster ist klein (typischerweise deutlich unter einer Sekunde) und schließt sich von selbst. Aber „meistens korrekt" reicht für eine Read-after-Write-Bestätigung nicht. Genau dafür gibt es starke Konsistenz.
Warum letztendliche Konsistenz entsteht
DynamoDB legt jede Partition auf drei Storage-Knoten ab — einem Primary und zwei Replikaten — über getrennte Availability Zones. Ein Write gilt als bestätigt, sobald er auf dem Primary und einem Replikat gelandet ist; zum dritten Knoten propagiert er anschließend asynchron.
Reads dürfen zur Lastverteilung von jedem der drei Knoten bedient werden. Ein letztendlich konsistenter Read kann einen Knoten treffen, der deinen jüngsten Write noch nicht hat — und liefert dann einen leicht veralteten Wert. Ein stark konsistenter Read geht an den Leader der Partition, der immer die zuletzt committeten Daten hält, und liefert deshalb nie veraltete Ergebnisse.
Diese Replikationsverzögerung ist der ganze Unterschied. Sie erklärt auch die 2×-Kosten: Starke Reads lassen sich nicht wie letztendlich konsistente über die Replikate verteilen, also berechnet DynamoDB ihnen die doppelte Kapazität.
Die Kosten, konkret
Reads werden in Read Capacity Units (RCU) gemessen, jede deckt bis zu 4 KB ab. Eine RCU
kauft einen stark konsistenten Read oder zwei letztendlich konsistente Reads eines 4 KB
großen Items. ConsistentRead=true auf einem heißen Lesepfad umzulegen verdoppelt also dessen
Lesekosten — auf einem Endpunkt mit viel Traffic ist das ein Posten, den du merkst.
Rechne den Unterschied für deine eigenen Item-Größen und Requestraten im DynamoDB Preisrechner durch, bevor du starke Reads zum Standard machst — es lohnt sich selten, flächendeckend doppelt zu zahlen.
Wo starke Reads verfügbar sind — und wo nicht
| Read gegen | Stark konsistent? |
|---|---|
| Basistabelle | Ja — mit ConsistentRead=true anfordern |
| Local Secondary Index (LSI) | Ja — dasselbe Opt-in wie die Basistabelle |
| Global Secondary Index (GSI) | Nein — nur letztendlich, kein Override |
Ein GSI führt seine eigene Kopie der Daten, asynchron aus der Basistabelle repliziert, und kann deshalb nie einen starken Read anbieten. Braucht ein Zugriffsmuster wirklich Read-after-Write und du wolltest es aus einem GSI bedienen, ist das ein Signal, es stattdessen aus der Basistabelle oder einem LSI zu bedienen.
Fallstricke + nächste Schritte
- Mach starke Reads nicht zum Standard. Die meisten Reads vertragen ein veraltetes Fenster von unter einer Sekunde; überall 2× zu zahlen ist verbranntes Geld.
- Erwarte von einem GSI kein Read-after-Write. Er ist per Design letztendlich konsistent — siehe warum ein GSI letztendlich konsistent ist.
- Transaktionen lesen stark.
TransactGetItemsist immer stark konsistent — siehe DynamoDB Transaktionen. - Konsistenz hängt an der Kapazität. Der 2×-Multiplikator geht direkt in die Kostenplanung von On-Demand vs. Provisioned ein.
Du willst deine DynamoDB-Tabellen und Indexe erkunden, ohne API-Aufrufe zu schreiben? Lade DynoTable herunter und sieh dir deine Daten direkt an.
RCU-Vergleich, durchgerechnet
Zwei Reads desselben 6 KB großen Items auf der Basistabelle:
| Modus | 4-KB-Blöcke | Verbrauchte RCU | Wann einsetzen |
|---|---|---|---|
| Stark konsistent | 2 (6 KB aufgerundet) | 2 RCU | Bestätigungsbildschirme nach dem eigenen Write |
| Letztendlich konsistent | 2 | 1 RCU | Dashboards, Listen, Analysen |
Bei 1.000 solcher Reads pro Sekunde kostet der starke Modus grob das Doppelte der
On-Demand-Leseausgaben des letztendlich konsistenten Modus — rechne das Delta im
Preisrechner durch, bevor du einen heißen Pfad
global auf ConsistentRead=true umstellst.
BatchGetItem-Konsistenz
Jeder Tabelleneintrag in BatchGetItem kann ConsistentRead unabhängig setzen. Ein
Dashboard, das ein Nutzerprofil (stark) und zugehörige Einstellungen (letztendlich) lädt, darf
die Flags in einem Batch-Aufruf mischen — die Regeln zur Verfügbarkeit starker Reads pro
Tabelle gelten weiterhin (kein starker Read auf einem GSI).
Read-after-Write im Anwendungscode
Muster für die Bestätigung einer Profilaktualisierung:
UpdateItemmit der neuen E-Mail.- Direkt danach
GetItemmitConsistentRead: trueauf der Basistabelle.
Schritt 2 kostet die doppelte RCU eines letztendlich konsistenten Reads, garantiert aber, dass der Bestätigungsbildschirm zum Write passt. Bei Hintergrund-Aggregationen, die eine Verzögerung unter einer Sekunde vertragen, lässt du starke Reads weg.
DynoTable-Standardeinstellungen
Explorative Reads in DynoTable laufen als letztendlich konsistente Abfragen auf der Basistabelle, solange du in den erweiterten Einstellungen keine strengere Semantik wählst — das passt zu den meisten Dashboard-Anwendungsfällen. Nach dem Stagen eines Writes zeigt der Refresh im Item-Editor die committeten Werte aus der erfolgreichen Antwort, ohne dass du für den Normalfall einen eigenen Konsistenz-Schalter brauchst.
Nimm den Query Builder, um Beispiel-Reads mit explizit gesetztem
ConsistentRead auszugeben, wenn du SDK-Code in Dienste kopierst, die
Read-after-Write-Garantien brauchen.
Hinweis zu Global Tables
Global Tables replizieren asynchron über Regionen hinweg. Starke Konsistenz gilt
innerhalb des Replikats einer Region, nicht global. Ein Write in us-east-1 ist in
eu-west-1 nicht sofort stark lesbar — plane die regionsübergreifende UX entsprechend.
Siehe Global Tables für die zu erwartende Replikationsverzögerung.