【问题标题】:Can I Read/Write from separate actors with same PersistenceId?我可以从具有相同 PersistenceId 的不同参与者读/写吗?
【发布时间】:2021-03-23 15:54:46
【问题描述】:

Petabridge blog's Akka.Persistence intro 明确表示您不能有多个具有相同 PersistenceId 的演员:

PersistenceId 字段很重要 - 它唯一标识了一个使用 Akka.Persistence 持久化其状态的实体,并且在任何给定时间对于单个 PersistenceId 都应该只有一个持久化参与者。

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

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

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

【问题讨论】:

标签: akka.net akka.net-persistence


【解决方案1】:

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

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

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

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

您可以通过覆盖Persistent ViewReceive 方法从日志中加载。此方法的参数是一个对象,因此您需要将该对象强制转换为您通过 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;
}

【讨论】:

  • 不错。持久视图是否支持从日志加载(与 Recover() 一样)? Doc 似乎只提到了快照。
  • @Gigi - 用几个关于访问持久视图中的事件的 cmets 更新了我的答案。希望这会有所帮助
  • 看起来是一种有趣的缓存方法。感谢分享!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-24
  • 2011-10-20
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-22
相关资源
最近更新 更多