0

Petabridge博客的 Akka.Persistence 介绍清楚地表明,您不能有多个具有相同 PersistenceId 的演员:

PersistenceId字段很重要——它唯一地标识了一个使用 Akka.Persistence 持久化其状态的实体,并且在任何给定时间对于单个PersistenceId.

[...] 所以想象一下,如果您有两个具有相同 PersistenceId 但序列号不同的演员写入同一个商店。这将是混乱的,并且不可避免地会出错 - 这就是为什么每个 PersistenceId 在您的 ActorSystem 中都是全球唯一的至关重要的原因(至少对于所有写入该商店的演员来说)。

我可以想到一个场景,您将有两个独立的参与者:一个负责将持久性状态保存到数据库(即调用Persist()),另一个负责在手动请求时重播来自日志的消息(即调用Recover())。读取和写入操作将由不同的参与者进行。只有一个人写过,也只有一个人读过。但是,两者都需要相同的 PersistenceId。

我相信在这种情况下,让两个参与者使用相同的 PersistenceId 应该是安全的。但是鉴于上面引用的上述警告,有什么理由说明这种方法在实践中可能是危险的?

4

1 回答 1

1

我可以想到一个场景,您将有两个单独的参与者:一个负责将持久性状态保存到数据库(即调用 Persist()),另一个负责在手动请求时重播来自日志的消息(即调用恢复())。读取和写入操作将由不同的参与者进行。只有一个人写过,也只有一个人读过。但是,两者都需要相同的 PersistenceId。

您需要的行为已经公开为Persistent ActorsPersistent Views。从文档:

虽然可以使用持久性参与者来生成和持久化事件,但视图仅用于读取基于它们的内部状态。与持久化参与者一样,视图有一个 PersistenceId 来指定要重新发送到当前视图的事件集合。然而,这个值应该与作为事件生产者的参与者的 PersistentId 相关联。

编辑:更新以提供有关如何在持久视图中访问事件的更多信息。

您可以通过覆盖Receivea 的方法从日志中加载Persistent View。此方法的参数是一个对象,因此您需要将该对象转换为您通过Persistent Actor.

Receive方法还处理您传递给视图的任何其他消息——例如来自表示层的读取请求。我通常在 View 内部存储一个事件列表,并从中返回一个自定义视图模型。

protected override bool Receive(object message)
{
    // if the message is a previously persisted event, update our internal list
    var e = message as MyEvent;
    if (e != null) _events.Add(e);
    return true;

    // if the message is a request for a view model, read from our list of stored events
    var r = message as ReadRequest;
    if (r == null) return false;
    Sender.Tell(new ViewModel(_events));
    return true;
}
于 2016-08-30T15:05:53.393 回答