Daten für strikte Konsistenz strukturieren

Datastore bietet hohe Verfügbarkeit, Skalierbarkeit und Langlebigkeit, da die Daten auf viele Rechner verteilt werden und eine synchrone Replikation ohne Master für einen großen geografischen Bereich verwendet wird. Bei diesem Design muss jedoch ein Kompromiss bei dem Schreibdurchsatz für eine einzelne Entitätengruppe in Kauf genommen werden, der auf ca. einen Commit-Vorgang pro Sekunde begrenzt ist. Es gibt auch Einschränkungen bei Abfragen oder Transaktionen, die mehrere Entitätengruppen umfassen. Auf dieser Seite werden diese Einschränkungen im Einzelnen beschrieben. Außerdem werden Best Practices zur Strukturierung der Daten im Hinblick auf starke Konsistenz bei gleichzeitiger Einhaltung der Anforderungen an den Schreibdurchsatz der Anwendung vorgestellt.

Konsistenzebenen

Datastore-Abfragen können Ergebnisse auf einer von zwei Konsistenzebenen liefern:

  • Abfragen mit strikter Konsistenz garantieren die aktuellsten Ergebnisse. Sie können jedoch länger dauern oder werden in bestimmten Fällen möglicherweise nicht unterstützt.
  • Abfragen mit Eventual Consistency werden im Allgemeinen schneller ausgeführt, können jedoch gelegentlich veraltete Ergebnisse zurückgeben.

Bei einer letztendlich konsistenten Abfrage wird auf die Indexe zur Erfassung der Ergebnisse ebenfalls mit Eventual Consistency zugegriffen. Daher geben derartige Abfragen gelegentlich Entitäten zurück, die nicht mehr mit den Abfragekriterien übereinstimmen. Außerdem können Entitäten weggelassen werden, die mit den Abfragekriterien übereinstimmen. Stark konsistente Abfragen sind transaktional konsistent, d. h. die Ergebnisse basieren auf einem einzelnen, konsistenten Snapshot der Daten.

Konsistenzgarantien

Die Ergebnisse von Abfragen werden je nach Art der Abfrage mit unterschiedlichen Konsistenzgarantieebenen zurückgegeben:

  • Ancestor-Abfragen: Abfragen, die für eine Entitätengruppe ausgeführt werden. Sie sind standardmäßig strikt konsistent, können jedoch in Abfragen mit Eventual Consistency umgewandelt werden. Dazu wird die Datastore-Leserichtlinie festgelegt (wie unten beschrieben).
  • Globale Abfragen (Abfragen, die nicht für eine Entitätengruppe ausgeführt werden) sind immer letztendlich konsistent.

In vielen Anwendungen kann Eventual Consistency (d. h. eine globale Abfrage über mehrere Entitätengruppen hinweg, die gelegentlich etwas veraltete Daten zurückgeben kann) akzeptiert werden, wenn eine breite Ansicht nicht zusammengehöriger Daten abgerufen wird. Danach wird dann Strong Consistency (eine Ancestor-Abfrage oder ein Lookup einer einzelnen Entität) verwendet, wenn eine einzelne Gruppe von eng zusammenhängenden Daten angezeigt oder bearbeitet wird. In derartigen Anwendungen ist die Gruppierung von eng zusammenhängenden Daten in Entitätengruppen im Allgemeinen ein guter Ansatz. Eine höhere Anzahl von Entitätengruppen erhöht den Durchsatz, während eine niedrigere Anzahl von Entitätengruppen das Volumen von Entitäten erhöht, die in einer einzelnen Ancestor-Abfrage gelesen werden können. In einer Anwendung muss dies berücksichtigt werden, um das richtige Verhältnis von Durchsatz und Konsistenz zu bestimmen.

Leserichtlinie für Datenspeicher

Zur Verbesserung der Leistung können Sie eine Leserichtlinie für eine Abfrage festlegen, damit die Ergebnisse letztendlich konsistent sind. (Mit der Datenspeicher API können Sie auch explizit eine Strong Consistency-Richtlinie festlegen, diese Einstellung hat jedoch keine praktischen Auswirkungen, weil globale Abfragen ungeachtet der Richtlinie immer letztendlich konsistent sind.)

Sie können letztendlich konsistente Lesezugriffe über die Leseoptionen des Abfrageobjekts aktivieren:

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore C# API.

Query query = new Query("Task")
    {
        Filter = Filter.HasAncestor(_db.CreateKeyFactory("TaskList")
            .CreateKey(keyName))
    };
    var results = _db.RunQuery(query,
        ReadOptions.Types.ReadConsistency.Eventual);

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Go API.

ancestor := datastore.NameKey("TaskList", "default", nil)
    query := datastore.NewQuery("Task").Ancestor(ancestor).EventualConsistency()

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Java API.

Query<Entity> query = Query.newEntityQueryBuilder()
        .setKind("Task")
        .setFilter(PropertyFilter.hasAncestor(
            datastore.newKeyFactory().setKind("TaskList").newKey("default")))
        .build();
    datastore.run(query, ReadOption.eventualConsistency());

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Node.js API.

const ancestorKey = datastore.key(['TaskList', 'default']);
    const query = datastore.createQuery('Task').hasAncestor(ancestorKey);

    query.run({consistency: 'eventual'});

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore PHP API.

$query = $datastore->query()
        ->kind('Task')
        ->hasAncestor($datastore->key('TaskList', 'default'));
    $result = $datastore->runQuery($query, ['readConsistency' => 'EVENTUAL']);

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Python API.

# Read consistency cannot be specified in google-cloud-python.

Ruby

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Ruby API.

ancestor_key = datastore.key "TaskList", "default"

    query = datastore.query("Task")
                     .ancestor(ancestor_key)

    tasks = datastore.run query, consistency: :eventual

Transaktionen und Konsistenzerwägungen

Datastore-Commits sind entweder transaktional, d. h. sie finden im Kontext einer Transaktion statt und die Mutationen der Transaktion werden entweder insgesamt oder gar nicht angewendet, oder sie sind nicht transaktional, d. h. die Mutationen können nicht insgesamt oder gar nicht angewendet werden.

Eine einzelne Transaktion kann eine beliebige Anzahl von Erstell-, Aktualisierungs- oder Löschmutationen enthalten. Um die Konsistenz der Daten aufrechtzuerhalten, stellt die Transaktion sicher, dass alle enthaltenen Mutationen auf den Datenspeicher als Einheit angewendet werden, oder wenn eine der Mutationen fehlschlägt, keine der Mutationen angewendet wird. Darüber hinaus basieren alle stark konsistenten Lesevorgänge (Ancestor-Abfragen oder lookup-Vorgänge) innerhalb derselben Transaktion auf einem einzelnen, konsistenten Snapshot der Daten. Stark konsistente Abfragen müssen einen Ancestor-Filter angeben. Abfragen, die an einer Transaktion teilnehmen, sind immer stark konsistent. Transaktionen können maximal 25 Entitätengruppen umfassen. Für letztendlich konsistente Lesezugriffe gelten diese Einschränkungen nicht. Sie können in vielen Fällen verwendet werden. Mit letztendlich konsistenten Lesezugriffen können Sie die Daten auf eine größere Anzahl von Entitätengruppen verteilen, sodass Sie einen höheren Schreibdurchsatz durch Ausführung von Commit-Vorgängen im Parallelverfahren für die verschiedenen Entitätengruppen erzielen können. Sie müssen jedoch die Eigenschaften von letztendlich konsistenten Lesezugriffen verstehen, um festlegen zu können, ob sie für Ihre Anwendung geeignet sind:

  • Die Ergebnisse dieser Lesezugriffe spiegeln möglicherweise die letzten Transaktionen nicht wider. Dies kann geschehen, weil diese Lesezugriffe nicht sicherstellen, dass die Replikate, mit denen sie ausgeführt werden, auf dem neuesten Stand sind. Stattdessen verwenden sie die Daten, die in dem Replikat zum Zeitpunkt der Abfrageausführung verfügbar sind.
  • Eine mit Commit durchgeführte Transaktion über mehrere Entitätengruppen hinweg kann scheinbar auf einige der Entitäten angewendet worden sein, auf andere jedoch nicht. Beachten Sie jedoch, dass eine Transaktion niemals scheinbar teilweise innerhalb einer einzelnen Entität angewendet wurde.
  • Die Abfrageergebnisse können Entitäten enthalten, die gemäß den Filterkriterien nicht hätten einbezogen werden sollen, und können Entitäten ausschließen, die hätten einbezogen werden sollen. Dies kann auftreten, weil die Snapshot-Version, mit der die Indexe gelesen wurden, nicht identisch mit der Snapshot-Version ist, mit der die Entität gelesen wurde.

Daten im Hinblick auf Konsistenz strukturieren

Zum besseren Verständnis, wie Daten im Hinblick auf Strong Consistency strukturiert werden sollen, vergleichen Sie zwei verschiedene Lösungen für eine einfache Aufgabenlistenanwendung. In der ersten Lösung wird jede Entität in ihrer eigenen neuen Entitätengruppe erstellt (d. h. jede Entität ist eine Stammentität):

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore C# API.

Entity task = new Entity()
    {
        Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
        ["category"] = "Personal",
        ["done"] = false,
        ["priority"] = 4,
        ["description"] = "Learn Cloud Datastore"
    };

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Go API.

type Task struct {
    	Category        string
    	Done            bool
    	Priority        float64
    	Description     string `datastore:",noindex"`
    	PercentComplete float64
    	Created         time.Time
    }
    task := &Task{
    	Category:        "Personal",
    	Done:            false,
    	Priority:        4,
    	Description:     "Learn Cloud Datastore",
    	PercentComplete: 10.0,
    	Created:         time.Now(),
    }

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Java API.

Key taskKey = datastore.newKeyFactory()
        .setKind("Task")
        .newKey("sampleTask");
    Entity task = Entity.newBuilder(taskKey)
        .set("category", "Personal")
        .set("done", false)
        .set("priority", 4)
        .set("description", "Learn Cloud Datastore")
        .build();

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Node.js API.

const task = {
      category: 'Personal',
      done: false,
      priority: 4,
      description: 'Learn Cloud Datastore',
    };

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore PHP API.

$task = $datastore->entity('Task', [
        'category' => 'Personal',
        'done' => false,
        'priority' => 4,
        'description' => 'Learn Cloud Datastore'
    ]);

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Python API.

task = datastore.Entity(client.key('Task'))
    task.update({
        'category': 'Personal',
        'done': False,
        'priority': 4,
        'description': 'Learn Cloud Datastore'
    })

Ruby

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Ruby API.

task = datastore.entity "Task" do |t|
      t["category"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end

Danach erfolgt eine Abfrage nach dem Entitätstyp Task für noch nicht erledigte Aufgaben mit Prioritäten größer als oder gleich 4, in absteigender Reihenfolge nach Priorität sortiert:

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore C# API.

Query query = new Query("Task")
    {
        Filter = Filter.And(Filter.Equal("done", false),
            Filter.GreaterThanOrEqual("priority", 4)),
        Order = { { "priority", PropertyOrder.Types.Direction.Descending } }
    };

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Go API.

query := datastore.NewQuery("Task").
    	Filter("Done =", false).
    	Filter("Priority >=", 4).
    	Order("-Priority")

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Java API.

Query<Entity> query = Query.newEntityQueryBuilder()
        .setKind("Task")
        .setFilter(CompositeFilter.and(
            PropertyFilter.eq("done", false), PropertyFilter.ge("priority", 4)))
        .setOrderBy(OrderBy.desc("priority"))
        .build();

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Node.js API.

const query = datastore
      .createQuery('Task')
      .filter('done', '=', false)
      .filter('priority', '>=', 4)
      .order('priority', {
        descending: true,
      });

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore PHP API.

$query = $datastore->query()
        ->kind('Task')
        ->filter('done', '=', false)
        ->filter('priority', '>=', 4)
        ->order('priority', Query::ORDER_DESCENDING);

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Python API.

query = client.query(kind='Task')
    query.add_filter('done', '=', False)
    query.add_filter('priority', '>=', 4)
    query.order = ['-priority']

Ruby

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Ruby API.

query = datastore.query("Task")
                     .where("done", "=", false)
                     .where("priority", ">=", 4)
                     .order("priority", :desc)

Da jedoch eine letztendlich konsistente Abfrage (und keine Ancestor-Abfrage) verwendet wird, enthalten die Abfrageergebnisse die neue Entität möglicherweise nicht. Dennoch sind nahezu alle Schreibvorgänge für letztendlich konsistente Abfragen kurz nach einem Commit-Vorgang verfügbar. Bei vielen Anwendungen reicht im Allgemeinen eine Lösung, die die Ergebnisse einer letztendlich konsistenten Abfrage im Kontext der eigenen Änderungen des aktuellen Nutzers bereitstellt, damit derartige Latenzen vollständig annehmbar sind.

Im Hinblick auf Strong Consistency besteht eine bessere Lösung darin, die Entitäten mit einem Ancestor-Pfad zu erstellen. Der Ancestor-Pfad identifiziert die gemeinsame Stammentität, in der die erstellten Entitäten gruppiert werden. In diesem Beispiel wird ein Ancestor-Pfad vom Typ TaskList mit dem Namen default verwendet:

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore C# API.

Key taskListKey = _db.CreateKeyFactory("TaskList").CreateKey(TestUtil.RandomName());
    Key taskKey = new KeyFactory(taskListKey, "Task").CreateKey("sampleTask");
    Entity task = new Entity()
    {
        Key = taskKey,
        ["category"] = "Personal",
        ["done"] = false,
        ["priority"] = 4,
        ["description"] = "Learn Cloud Datastore"
    };

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Go API.

parentKey := datastore.NameKey("TaskList", "default", nil)
    key := datastore.IncompleteKey("Task", parentKey)

    task := Task{
    	Category:    "Personal",
    	Done:        false,
    	Priority:    4,
    	Description: "Learn Cloud Datastore",
    }

    // A complete key is assigned to the entity when it is Put.
    var err error
    key, err = client.Put(ctx, key, &task)

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Java API.

Key taskKey = datastore.newKeyFactory()
        .addAncestors(PathElement.of("TaskList", "default"))
        .setKind("Task")
        .newKey("sampleTask");
    Entity task = Entity.newBuilder(taskKey)
        .set("category", "Personal")
        .set("done", false)
        .set("priority", 4)
        .set("description", "Learn Cloud Datastore")
        .build();

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Node.js API.

const taskKey = datastore.key([
      'TaskList',
      'default',
      'Task',
      'sampleTask',
    ]);

    const task = {
      key: taskKey,
      data: {
        category: 'Personal',
        done: false,
        priority: 4,
        description: 'Learn Cloud Datastore',
      },
    };

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore PHP API.

$parentKey = $datastore->key('TaskList', 'default');
    $key = $datastore->key('Task')->ancestorKey($parentKey);
    $task = $datastore->entity(
        $key,
        [
            'Category' => 'Personal',
            'Done' => false,
            'Priority' => 4,
            'Description' => 'Learn Cloud Datastore'
        ]
    );

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Python API.

key_with_parent = client.key(
        'TaskList', 'default', 'Task', 'sample_task')

    task = datastore.Entity(key=key_with_parent)

    task.update({
        'category': 'Personal',
        'done': False,
        'priority': 4,
        'description': 'Learn Cloud Datastore'
    })

Ruby

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Ruby API.

task_key = datastore.key [["TaskList", "default"], ["Task", "sampleTask"]]

    task = datastore.entity task_key do |t|
      t["category"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end

Danach können Sie eine stark konsistente Ancestor-Abfrage innerhalb der von der gemeinsamen Stammentität identifizierten Entitätengruppe ausführen:

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore C# API.

Query query = new Query("Task")
    {
        Filter = Filter.HasAncestor(_db.CreateKeyFactory("TaskList")
            .CreateKey(keyName))
    };

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Go API.

ancestor := datastore.NameKey("TaskList", "default", nil)
    query := datastore.NewQuery("Task").Ancestor(ancestor)

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Java API.

Query<Entity> query = Query.newEntityQueryBuilder()
        .setKind("Task")
        .setFilter(PropertyFilter.hasAncestor(
            datastore.newKeyFactory().setKind("TaskList").newKey("default")))
        .build();

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Node.js API.

const ancestorKey = datastore.key(['TaskList', 'default']);

    const query = datastore.createQuery('Task').hasAncestor(ancestorKey);

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore PHP API.

$ancestorKey = $datastore->key('TaskList', 'default');
    $query = $datastore->query()
        ->kind('Task')
        ->hasAncestor($ancestorKey);

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Python API.

# Query filters are omitted in this example as any ancestor queries with a
    # non-key filter require a composite index.
    ancestor = client.key('TaskList', 'default')
    query = client.query(kind='Task', ancestor=ancestor)

Ruby

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud Datastore finden Sie hier. Weitere Informationen finden Sie in der Referenzdokumentation zur Cloud Datastore Ruby API.

ancestor_key = datastore.key "TaskList", "default"

    query = datastore.query("Task")
                     .ancestor(ancestor_key)

Diese Lösung erzielt Strong Consistency, indem in eine einzelne Entitätengruppe pro Aufgabenliste geschrieben wird. Die Änderungen an der Aufgabenliste werden jedoch auch auf nicht mehr als genau einen Schreibvorgang pro Sekunde begrenzt (der unterstützte Grenzwert für Entitätengruppen). Wenn bei der Anwendung wahrscheinlich mehr Schreibvorgänge ausgeführt werden, sollten Sie eventuell andere Möglichkeiten in Erwägung ziehen. Beispiel: Wenn die Anwendung ein Gästebuch ist, bei dem Nutzer Nachrichten an ein öffentliches Forum posten können, könnten Sie die neuesten Posts in Memcache mit einem Ablaufzeitpunkt speichern und eine Mischung der letzten Posts aus Memcache und dem Datenspeicher anzeigen. Sie könnten sie auch in einem Cookie zwischenspeichern, einen Status in die URL setzen, oder eine ganz andere Lösung finden. Das Ziel besteht darin, eine Caching-Lösung zu finden, die Daten für den aktuellen Nutzer während des Zeitraums bereitstellt, in dem der Nutzer Beiträge an Ihre Anwendung postet. Wenn Sie einen lookup-Vorgang, eine Ancestor-Abfrage (vorausgesetzt die Leserichtlinie ist nicht auf Eventual Consistency gesetzt) oder einen Vorgang innerhalb einer Transaktion ausführen, werden immer die zuletzt geschriebenen Daten angezeigt.

Weitere Beispiele zur Verwendung von Transaktionen finden Sie hier.

Entitätengruppenbeschränkungen bei Transaktionen

Durch die Anordnung von Daten in Entitätengruppen kann begrenzt werden, welche Transaktionen ausgeführt werden können:

  • Alle Daten, auf die eine Transaktion zugreift, müssen in maximal 25 Entitätengruppen enthalten sein.
  • Wenn Sie Abfragen innerhalb einer Transaktion verwenden möchten, müssen die Daten so in Entitätengruppen angeordnet werden, dass Sie Ancestor-Filter angeben können, die mit den richtigen Daten übereinstimmen.
  • Es gibt einen Grenzwert für den Schreibdurchsatz von ca. einer Transaktion pro Sekunde für eine einzelne Entitätengruppe. Diese Begrenzung ist vorhanden, weil Datastore eine synchrone Replikation ohne Master jeder Entitätengruppe über einen breiten geografischen Bereich hinweg durchführt, um hohe Verlässlichkeit und Fehlertoleranz zu ermöglichen.

Weitere Informationen zur Aktualisierung von Entitäten und Indexen finden Sie im Artikel zur Transaktionsisolation.