Share via


立即和延遲確認

在本文中,您將了解立即和延遲確認之間的差異。

立即確認

對於許多應用程式,我們想要確保立即確認事件,使保存版本不會落後記憶體中的目前版本,而且我們不希望若 Grain 失敗而有遺失最新狀態的風險。 我們可以透過遵循下列規則來保證這點:

  1. 在 Grain 方法傳回之前,確認所有 RaiseEvent 呼叫使用 ConfirmEvents
  2. 在 Grain 方法傳回之前,確定 RaiseConditionalEvent 傳回的工作已完成。
  3. 避免使用 ReentrantAttributeAlwaysInterleaveAttribute 屬性,因此一次只能處理一個 Grain 呼叫。

如果我們遵循這些規則,這表示在引發事件之後,將事件寫入儲存體之前,無法執行其他 Grain 程式碼。 因此,您不可能觀察到記憶體版本與儲存體版本之間的不一致。 雖然這通常正是我們想要的,但也有一些潛在的缺點。

潛在缺點

  • 如果遠端叢集或儲存體的連線暫時中斷,則 Grain 會變成無法使用:實際情況是,Grain 停滯在等候確認事件而無法執行任何程式碼,這可能會耗費一段不確定時間 (記錄一致性通訊協定會持續重試,直到儲存體連線能力還原為止)。

  • 當處理單一 Grain 執行個體的大量更新時,一次確認一個更新可能會變得非常沒有效率,例如,造成低輸送量。

延遲確認

若要改善上述情況的可用性和輸送量,Grain 可以選擇執行下列其中一項或兩項作業:

  • 允許 Grain 方法引發事件,而不需等候確認。
  • 允許重新進入,因此即使先前的呼叫停滯在等候確認,Grain 仍可繼續處理新的呼叫。

這表示 Grain 可以在某些事件仍在待確認期間執行程式碼。 JournaledGrain<TGrainState,TEventBase> API 有一些特定的佈建,可讓開發人員對於如何處理目前為「執行中」的未確認事件進行精確地控制。

您可以檢查下列屬性,找出目前未確認的事件:

IEnumerable<EventType> UnconfirmedEvents { get; }

此外,由於 JournaledGrain<TGrainState,TEventBase>.State 屬性傳回的狀態不包含未確認事件的效果,因此有替代屬性

StateType TentativeState { get; }

這個屬性會傳回「暫訂」狀態,該狀態取自透過套用所有未確認事件而得的「狀態」。 暫訂狀態基本上是確認所有未確認事件之後,可能會變成下一個確認狀態的「最佳猜測」。 不過,我們無法保證猜測會成真,因為 Grain 可能會失敗,或是因為事件可能與其他事件競爭失敗,導致事件遭取消 (如果是條件式事件的話),或導致事件出現在序列中的位置比預期的位置更後方 (如果不是條件式事件的話)。

並行保證

請注意,Orleans 回合型排程 (合作式並行) 保證即使使用重新進入或延遲確認也一律套用。 這表示,即使有數個方法正在進行中,只有一個方法可以主動執行—所有其他方法會停滯在等候中,因此平行執行緒永遠不會造成任何真正的競爭。

請特別注意:

這些保證假設使用者程式碼會保留在有關工作和 async/await 的建議做法範圍內 (特別是,不會使用執行緒集區工作,或只將執行緒集區工作用於未呼叫 Grain 功能且已正確等候的程式碼)。