2017-03-20 3 views
1

Ich verstehe, dass NDB Abfragen (Lesen) schließlich konsistent sind. Aber was ist mit Löschen und Schreiben?NDB löschen & Konsistenz

Zum Beispiel wird den Code unten laufen immer (schließlich) führen zu einer defekten widget in unserem Datenspeicher sein:

# get rid of defective widgets 
defective_widgets = Widget.query(Widget.defective == True).fetch(keys_only=True) 
ndb.delete_multi(defective_widgets) 

# uh oh, we have a new one 
Widget(defective=True).put() 

... oder gibt es eine Möglichkeit, dass der Löschvorgang die neuen entfernen könnte defektes Widget?

Antwort

1

"... besteht die Möglichkeit, dass der Löschvorgang das neue fehlerhafte Widget entfernen könnte?"

Nr

haben „den Code unten läuft immer (schließlich) führen zu einer defekten Widget ist in unserem Datenspeicher“

auch Nein, es gibt eine Möglichkeit, vorherige defekte Widgets können nicht wurde gelöscht.

Der Cloud-Datenspeicher ist bei Suchvorgängen (get-by-key) und Vorfahrenanfragen sehr konsistent. Es ist schließlich bei Nicht-Vorfahren-Abfragen konsistent. Ein Weg, um darüber nachzudenken, wie Cloud Datastor Konsistenz behandelt ist:

  • Entity Writes wird synchron geschrieben/gelöscht
  • Indizes asynchron aktualisiert werden (die meiste Zeit unmittelbar, aber nicht immer)
  • Entity-Gruppen definieren Datenlokalität, zwingen so Vorfahr Abfragen starke Konsistenz

ist bei Ihrem Beispiel schauen wir

Lassen Sie uns zunächst einen Beispieldatensatz einrichten. Einige Code fügt neue defekte Widgets:

WidgetA(defective=True).put() 
WidgetB(defective=True).put() 
WidgetC(defective=True).put() 

Jetzt haben wir:

  • WidgetA(defective: True)
  • WidgetB(defective: True)
  • WidgetC(defective: True)

Doing-Lookups (durch Schlüssel erhalten) immer geben Sie diese 3 Entitäten zurück, da Suchvorgänge sehr konsistent sind.

Unmittelbar nachdem diese drei Widgets hinzugefügt wurden, möchte einige Code eine Liste aller defekten Widgets erhalten.

defective_widgets = Widget.query(Widget.defective == True).fetch(keys_only=True) 

gibt dann einen Anruf, sie zu löschen alle:

ndb.delete_multi(defective_widgets) 

Welche Daten wir jetzt in der Datenbank haben? Die Antwort ist jede Kombination von WidgetA, B, & C, oder keiner von ihnen oder sogar alle von ihnen. Warum? Da die ausgegebene Abfrage schließlich konsistent war und davon abhing, ob die Indexaktualisierungen angewendet wurden oder nicht, wird bestimmt, ob die Liste der Entitätsschlüssel in defective_widgets.

Also an diesem Punkt, nachdem Sie letzten Widget(defective=True).put() ausführen, könnten wir irgendwo zwischen 1 und 4 defekte Widgets in Ihrer Datenbank haben.

Wie können Sie dies vermeiden?

Option 1 (Entity-Gruppen): Wenn defekte Widgets werden mit einer Rate von 1 Transaktion pro Sekunde oder weniger immer geschrieben/aktualisiert, dann können Sie sie alle in einer einzigen Einheit Gruppe setzen, Ihre Abfrage geändert werden eine Vorfahrenabfrage = und dann wird alles schließlich konsistent sein. Hinweis: Wenn Sie Widgetschreibvorgänge/-updates in einer Transaktion zusammenfassen können, werden alle diese Schreibvorgänge nur als 1 Transaktion gezählt. Wenn Sie also beispielsweise 500 Widgets miteinander mischen, können Sie 500 Widgets pro Sekunde ausführen.

Option 2 (Soft-Löschen): Wenn Ihre Schreibrate zu hoch ist, können Sie ein Soft-Delete-System implementieren. Eine einzelne Entität (zwischengespeichert, nennen wir sie "Versionsentität") speichert eine monoton steigende Versionsnummer (Ganzzahl). Jedes neue defekte Widget, das geschrieben wird, speichert diese Nummer auch in einer Eigenschaft namens 'version'. Wenn Sie eine Reihe von Widgets löschen möchten, erhöhen Sie die Anzahl in Version Entity um eins und drehen Sie eine Abfrage für alle Widgets mit einer Version, die kleiner als die neue Versionsnummer ist. Überprüfen Sie bei jeder Abfrage, die Widgets verarbeitet, ob die Version kleiner ist als die aktuelle Versionsnummer und wenn ja, verwerfen Sie sie aus dem Prozess (sie wird gelöscht). Sie können es optimieren, damit die Abfragen nicht die Mehrheit der gelöschten Elemente zurückgeben, indem Sie den Filter version = current einschließen.

+1

super hilfreich - danke! –

0

Wenn Sie ein neues defekte Widget nach die Löschvorgänge warum fertig zu schaffen würden Sie erwarten, dass es von einem früheren Code, der bereits ausgeführt entfernt werden? Die .fetch(keys_only=True) Zeile 2 hat bereits die Liste der vorhandenen Schlüssel aus dem Datenspeicher gezogen (die neue fehlerhafte Entität existierte zu diesem Zeitpunkt noch nicht). Daher gibt es in der nächsten Zeile keine Möglichkeit, über das neue fehlerhafte Widget zu erfahren Sie haben nicht .put() noch & so wird es nicht gelöscht werden.

+0

das ist, was ich erwarten würde. Ich sehe etwas rätselhaftes in unserem Code, das vielleicht etwas anderes vermuten lässt, also überprüfe ich meine Annahmen doppelt. Wenn Sie die Operationen rückgängig machen, glaube ich, dass Sie möglicherweise ein Widget erstellen und dann * nicht * löschen können, da die Abfrage das neue Widget aufgrund der möglichen Konsistenz (noch) nicht zurückgibt. meine Frage ist, mit dem obigen Code, könnte die Abfrage versehentlich ein Widget (sofort) * nach * der Abfrage Operation erstellt, und löschen Sie dieses Widget? –