共用方式為


存取、儲存、移除 Reliable Actors 狀態

Reliable Actors 是可封裝邏輯和狀態並穩定維持狀態的單一執行緒物件。 每個動作項目執行個體都有自己的狀態管理員︰以可靠方式儲存索引鍵/值組的字典式資料結構。 狀態管理員是包住狀態供應器的包裝函式。 可以用來儲存資料,無論所用的是何種持續性設定

狀態管理員索引鍵必須是字串。 值是泛型值,而且可以是任何類型,包括自訂類型。 儲存在狀態管理員中的值必須是可進行資料合約序列化的,因為根據動作項目的狀態持續性設定,它們可能會在複寫期間透過網路傳輸至其他節點,而且可能會寫入磁碟。

狀態管理員會公開一般字典方法來管理狀態,類似於在可靠的字典中找到的項目。

如需相關資訊,請參閱管理動作項目狀態的最佳做法

存取狀態

狀態可以透過狀態管理員依索引鍵來存取。 狀態管理員方法全都是非同步的,因為當動作項目具有保存的狀態時,它們可能需要磁碟 I/O。 第一次存取時,會將狀態物件快取於記憶體中。 重複存取作業會從記憶體中直接存取物件並以同步方式傳回,而不會造成磁碟 I/O 或非同步內容切換的負擔。 狀態物件會在下列情況中從快取移除︰

  • 從狀態管理員中擷取物件之後,動作項目方法會擲回未處理的例外狀況。
  • 動作項目會在已停用之後或因為失敗而重新啟動。
  • 狀態供應器會將狀態分頁到磁碟。 這個行為取決於狀態供應器實作。 Persisted 設定的預設狀態供應器具有這個行為。

如果索引鍵的項目不存在,您可以使用會擲回 KeyNotFoundException(C#) 或 NoSuchElementException(Java) 的標準 Get 作業來擷取狀態:

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task<int> GetCountAsync()
    {
        return this.StateManager.GetStateAsync<int>("MyState");
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture<Integer> getCountAsync()
    {
        return this.stateManager().getStateAsync("MyState");
    }
}

如果索引鍵的項目不存在,您也可以使用不會擲回任何項目的 TryGet 方法來擷取狀態:

class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task<int> GetCountAsync()
    {
        ConditionalValue<int> result = await this.StateManager.TryGetStateAsync<int>("MyState");
        if (result.HasValue)
        {
            return result.Value;
        }

        return 0;
    }
}
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture<Integer> getCountAsync()
    {
        return this.stateManager().<Integer>tryGetStateAsync("MyState").thenApply(result -> {
            if (result.hasValue()) {
                return result.getValue();
            } else {
                return 0;
            });
    }
}

儲存狀態

狀態管理員擷取方法會傳回本機記憶體中物件的參考。 在本機記憶體中單獨修改此物件並不會永久儲存該物件。 從狀態管理員中擷取並修改物件時,必須將它重新插入狀態管理員,才能永久儲存。

您可以使用無條件的 Set 來插入狀態,這相當於 dictionary["key"] = value 語法︰

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task SetCountAsync(int value)
    {
        return this.StateManager.SetStateAsync<int>("MyState", value);
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture setCountAsync(int value)
    {
        return this.stateManager().setStateAsync("MyState", value);
    }
}

您可以使用 Add 方法來新增狀態。 這個方法會在它新增已存在的索引鍵時擲回 InvalidOperationException(C#) 或 IllegalStateException(Java)。

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task AddCountAsync(int value)
    {
        return this.StateManager.AddStateAsync<int>("MyState", value);
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture addCountAsync(int value)
    {
        return this.stateManager().addOrUpdateStateAsync("MyState", value, (key, old_value) -> old_value + value);
    }
}

您也可以使用 TryAdd 方法來新增狀態。 此方法不會在它嘗試新增已存在的索引鍵時擲回任何項目。

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task AddCountAsync(int value)
    {
        bool result = await this.StateManager.TryAddStateAsync<int>("MyState", value);

        if (result)
        {
            // Added successfully!
        }
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture addCountAsync(int value)
    {
        return this.stateManager().tryAddStateAsync("MyState", value).thenApply((result)->{
            if(result)
            {
                // Added successfully!
            }
        });
    }
}

在動作項目方法結束時,狀態管理員會自動儲存透過插入或更新作業所新增或修改的任何值。 根據所使用的設定,「儲存」可以包括保存到磁碟與複本。 尚未經過修改的值不會保存或複寫。 如果未修改任何值,儲存作業就不會有任何動作。 如果儲存失敗,將會捨棄已修改的狀態並重新載入原始的狀態。

您也可以呼叫動作項目基底上的 SaveStateAsync 方法來手動儲存狀態︰

async Task IMyActor.SetCountAsync(int count)
{
    await this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value);

    await this.SaveStateAsync();
}
interface MyActor {
    CompletableFuture setCountAsync(int count)
    {
        this.stateManager().addOrUpdateStateAsync("count", count, (key, value) -> count > value ? count : value).thenApply();

        this.stateManager().saveStateAsync().thenApply();
    }
}

移除狀態

您可以藉由呼叫 Remove 方法,從動作項目的狀態管理員中永久移除狀態。 這個方法會在它嘗試移除不存在的索引鍵時擲回 KeyNotFoundException(C#) 或 NoSuchElementException(Java)。

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task RemoveCountAsync()
    {
        return this.StateManager.RemoveStateAsync("MyState");
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture removeCountAsync()
    {
        return this.stateManager().removeStateAsync("MyState");
    }
}

您也可以使用 TryRemove 方法永久移除狀態。 此方法不會在它嘗試移除不存在的索引鍵時擲回任何項目。

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task RemoveCountAsync()
    {
        bool result = await this.StateManager.TryRemoveStateAsync("MyState");

        if (result)
        {
            // State removed!
        }
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture removeCountAsync()
    {
        return this.stateManager().tryRemoveStateAsync("MyState").thenApply((result)->{
            if(result)
            {
                // State removed!
            }
        });
    }
}

下一步

儲存在 Reliable Actors 中的狀態必須先經過序列化,才能寫入到磁碟中並進行複寫來提供高可用性。 深入了解動作項目類型序列化

接著,深入了解動作項目診斷與效能監視