Fortgeschritten7 Min. Lesezeit

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=true anfordern.
  • 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.

sync, bestätigtasync, kurz verzögertkann einen nachhinkendenKnoten treffenSchreiben: neue E-MailPrimärknotenReplikat 1Replikat 2Stark konsistenter ReadLetztendlich konsistenter Read

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 gegenStark konsistent?
BasistabelleJa — 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. TransactGetItems ist 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:

Modus4-KB-BlöckeVerbrauchte RCUWann einsetzen
Stark konsistent2 (6 KB aufgerundet)2 RCUBestätigungsbildschirme nach dem eigenen Write
Letztendlich konsistent21 RCUDashboards, 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:

  1. UpdateItem mit der neuen E-Mail.
  2. Direkt danach GetItem mit ConsistentRead: true auf 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.

Aktualisiert