Freigeben über


Sofortige und verzögerte Bestätigungen

In diesem Artikel lernen Sie die Unterschiede zwischen sofortigen und verzögerten Bestätigungen kennen.

Sofortige Bestätigung

Bei vielen Anwendungen möchten wir sicherstellen, dass Ereignisse sofort bestätigt werden, damit die persistente Version nicht hinter der aktuellen Version im Arbeitsspeicher zurückbleibt und wir nicht riskieren, den neuesten Zustand zu verlieren, wenn das Grain fehlschlägt. Wir können dies garantieren, indem wir die folgenden Regeln beachten:

  1. Bestätigen Sie alle RaiseEvent-Aufrufe mithilfe von ConfirmEvents, bevor die Grain-Methode zurückgegeben wird.
  2. Stellen Sie sicher, dass von RaiseConditionalEvent zurückgegebenen Aufgaben abgeschlossen werden, bevor die Grain-Methode zurückgegeben wird.
  3. Vermeiden Sie ReentrantAttribute- oder AlwaysInterleaveAttribute-Attribute, damit nur ein Grainaufruf gleichzeitig verarbeitet werden kann.

Wenn wir diese Regeln befolgen, bedeutet dies, dass nach dem Auslösen eines Ereignisses kein anderer Graincode ausgeführt werden kann, bis das Ereignis in den Speicher geschrieben wurde. Deshalb ist es unmöglich, Inkonsistenzen zwischen der Version im Arbeitsspeicher und der Version im Speicher festzustellen. Dies ist zwar häufig genau das, was wir wollen, hat aber auch einige potenzielle Nachteile.

Potenzielle Nachteile

  • Wenn die Verbindung mit einem Remotecluster oder -speicher vorübergehend unterbrochen wird, ist das Grain nicht mehr verfügbar: Effektiv heißt das, dass das Grain keinen Code ausführen kann, während es mit dem Warten auf die Bestätigung der Ereignisse feststeckt, was von unbegrenzter Dauer sein kann (das Protokollkonsistenzprotokoll unternimmt immer wieder Wiederholungsversuche, bis die Speicherkonnektivität wiederhergestellt wird).

  • Wenn Sie viele Aktualisierungen für eine einzelne Graininstanz verarbeiten, kann es sehr ineffizient sein, diese einzeln zu bestätigen, was beispielsweise zu einem schlechten Durchsatz führt.

Verzögerte Bestätigung

Um die Verfügbarkeit und den Durchsatz in den oben genannten Situationen zu verbessern, können Grains eine oder beide der folgenden Aktionen ausführen:

  • Grain-Methoden das Auslösen von Ereignissen erlauben, ohne auf die Bestätigung zu warten.
  • Reentranz zulassen, damit das Grain neue Aufrufe auch dann weiter verarbeiten kann, wenn vorherige Aufrufe beim Warten auf die Bestätigung hängen bleiben.

Dies bedeutet, dass Graincode ausgeführt werden kann, während sich einige Ereignisse noch im Bestätigungsprozess befinden. Die JournaledGrain<TGrainState,TEventBase>-API enthält einige spezifische Vorkehrungen, um Entwicklern die präzise Kontrolle über den Umgang mit nicht bestätigten Ereignissen zu verschaffen, die sich derzeit In Flight befinden.

Die folgende Eigenschaft kann untersucht werden, um herauszufinden, welche Ereignisse derzeit nicht bestätigt sind:

IEnumerable<EventType> UnconfirmedEvents { get; }

Da der von der JournaledGrain<TGrainState,TEventBase>.State-Eigenschaft zurückgegebene Zustand außerdem nicht die Auswirkungen nicht bestätigter Ereignisse enthält, gibt es eine alternative Eigenschaft.

StateType TentativeState { get; }

Die einen „vorläufigen“ Zustand zurückgibt, der aus dem „Zustand“ (State) abgerufen wird, indem alle nicht bestätigten Ereignisse angewendet werden. Der vorläufige Zustand ist im Wesentlichen eine „beste Vermutung“ darüber, was wahrscheinlich der nächste bestätigte Zustand wird, nachdem alle nicht bestätigten Ereignisse bestätigt wurden. Es gibt jedoch keine Garantie dafür, dass dieser tatsächlich eintreten wird, da das Grain fehlschlagen kann, oder weil ein Race zwischen Ereignissen stattfindet, das diese verlieren können, wodurch sie abgebrochen werden (wenn sie bedingt sind) oder an einer späteren Position in der Sequenz erscheinen, als erwartet (wenn sie bedingungslos sind).

Parallelitätsgarantien

Beachten Sie, dass rundenbasierte Aufgabenplanungsgarantien von Orleans (kooperative Parallelität) immer gelten, auch wenn Reentranz oder verzögerte Bestätigung verwendet wird. Dies bedeutet, dass, obwohl möglicherweise mehrere Methoden in Arbeit sind, nur eine aktiv ausgeführt werden kann – alle anderen sind bei „await“ hängen geblieben, sodass es nie zu echten Races kommt, die durch parallele Threads verursacht werden.

Beachten Sie insbesondere Folgendes:

  • Die Eigenschaften State, TentativeState, Version und UnconfirmedEvents können sich während der Ausführung einer Methode ändern.
  • Aber solche Änderungen können nur eintreten, während sie bei einem „await“ hängen bleiben.

Diese Garantien setzen voraus, dass der Benutzercode innerhalb der empfohlenen Vorgehensweise in Bezug auf Aufgaben und async/await bleibt (insbesondere dass er keine Threadpoolaufgaben verwendet, oder sie nur für Code verwendet, der keine Grainfunktionalität aufruft, und für die das „await“ ordnungsgemäß durchgeführt wird).