即時および遅延確認

この記事では、即時および遅延確認の違いについて学習します。

即時確認

多くのアプリケーションに対して、ユーザーは永続化されたバージョンがメモリ内の現在のバージョンよりも遅れないように、イベントがすぐに確認されるようにし、グレインが失敗した場合に最新の状態を失うリスクを回避したいと考えています。 次の規則に従うことで、これが保証されます。

  1. グレイン メソッドが返される前に、ConfirmEvents を使用してすべて RaiseEvent の呼び出しを確認してください。
  2. グレイン メソッドが返される前に、RaiseConditionalEvent によって返されるタスクが完了することを確認してください。
  3. ReentrantAttribute または AlwaysInterleaveAttribute 属性は避けて、一度に 1 つのグレイン コールしか処理できないようにしてください。

これらのルールに従うと、イベントが発生した後、イベントがストレージに書き込まれるまで、他のグレイン コードを実行できなくなります。 そのため、メモリ内のバージョンとストレージ内のバージョンの間の不整合を調べることはできません。 これは多くの場合、私たちが望むものですが、潜在的な欠点もいくつかあります。

潜在的な欠点

  • リモート クラスターまたはストレージへの接続が一時的に中断されると、グレインは使用できなくなります。事実上、グレインはイベントの確認を待機してスタックしている間は、コードを実行できず、これには、無期限に時間がかかるおそれがあります (ログ整合性プロトコルは、ストレージ接続が復元されるまで再試行を続けます)。

  • 1 つのグレイン インスタンスに対して多数の更新を処理する場合、それらを一度に 1 つずつ確認すると、スループットが低下するなど、非常に非効率的になることがあります。

遅延確認

上記の状況で可用性とスループットを向上させるために、グレインでは次のいずれかまたは両方を行うことを選択できます。

  • グレイン メソッドが確認を待たずにイベントを発生させる。
  • 再入を許可して、前の呼び出しが確認を待機してスタックしている場合でも、グレインが新しい呼び出しを処理し続けられるようにする。

これは、一部のイベントがまだ確認中である間にグレイン コードを実行できるということです。 JournaledGrain<TGrainState,TEventBase> API には、現在 "実行中" の未確認のイベントに対処する方法を開発者が正確に制御できるようにするためのいくつかの特定のプロビジョニングがあります。

次のプロパティを調べると、現在確認されていないイベントを見つけることができます。

IEnumerable<EventType> UnconfirmedEvents { get; }

また、JournaledGrain<TGrainState,TEventBase>.State プロパティによって返される状態には未確認のイベントの影響が含まれていないため、代替プロパティがあります

StateType TentativeState { get; }

未確認のすべてのイベントを適用して "State" から取得した "仮の" 状態が返されます。 仮の状態は、すべての未確認のイベントが確認された後に、次に確認された状態になる可能性が高いという点で、本質的に "最適な推測" です。 ただし、実際に行われる保証はありません。それは、グレインが失敗するおそれがある、またはイベントが他のイベントと競合して失われるおそれがあるため、それらが (条件付きの場合) キャンセルされる、または、(無条件の場合) シーケンス内で予想より後方の位置に出現する可能性があるためです。

コンカレンシーの保証

再入または遅延確認を使用する場合でも、Orleans ターンベースのスケジュール設定 (協調コンカレンシー) の保証が常に適用されることに留意してください。 つまり、複数のメソッドが進行中であっても、アクティブに実行できるのは 1 つだけです。他のメソッドはすべて待機状態でスタックするため、並列スレッドによって生じる真の競合はありません。

特に、次の点にご注意ください。

  • プロパティ StateTentativeStateVersionUnconfirmedEvents は、メソッドの実行中に変更できます。
  • しかし、このような変更は、待機中でスタックしている間にのみ発生します。

これらの保証は、ユーザー コードがタスクと async/await に関する推奨されるプラクティスの範囲内に留まっていることを前提としています (特に、スレッド プール タスクを使用しない、グレイン機能を呼び出さず、適切に待機しているコードに対してのみ使用する点)。