在池中跨 Akka Actor 实例共享可变数据

Posted

技术标签:

【中文标题】在池中跨 Akka Actor 实例共享可变数据【英文标题】:Sharing mutable data across Akka actor instances in a pool 【发布时间】:2017-12-18 15:08:24 【问题描述】:

我在互联网上找到的大多数 Akka 材料,包括许多 SO 问题都指出,我们应该在处理它们的 actor 中维护相关数据。不鼓励使用锁定机制

我正在开发基于 Akka Actor 的 Java 服务,该服务维护大量动态数据。以前我使用写时复制机制进行数据更新,但是由于预期的更新速率,这可能会导致下一个版本出现性能问题(特别是高 GC 活动)。

假设我有一个管理股票信息的演员 (StockManagerActor)。经常阅读和更新股票价格。 (我更喜欢让一个单独的参与者接收更新并提交它们,另一个参与者在需要时读取股票价格。但我不能这样做,因为它会使可变的股票数据在不同类型的参与者之间共享) 所以 StockManagerActor 处理两种类型的消息。 UpdateStockMessageGetStockMessage。当我们想到这个actor的单个实例正在运行时,一切似乎都很好,因为没有跨actor共享数据。

我担心如果我只有一个 StockManagerActor 在系统中运行,当股市高度活跃时,它的收件箱可能会迅速增长。所以我想要一个 StockManagerActor 池来同时处理消息。但是在这种情况下,不同的actor实例会同时进行更新/获取操作。 当 updateStock() 阻塞(在单独的调度程序中)和非阻塞时,这种场景有哪些好的设计?

StockManagerActor extends UntypedActor
    StockStroe stockStore;
    // Only StockManagerActors use the StockStore which is
    // Initially populated from outside of actor system. Methods are not
    // thread safe

    public StockManagerActor()
        stockStore = StockStore.getInstanceFor(this);
    

    @Override
    public void onReceive(Object message) throws Exception 
        if(message instanceof UpdateStockMessage)
            UpdateStockMessage updateMessage = (UpdateStockMessage)message;
            stockStore.updateStock(updateMessage)
        else if(message instanceof GetStockMessage)
            GetStockMessage getMessage = (GetStockMessage)message;
            Stock stock = stockStore.getStock(getMessage.getSymbol());
            // stock here is immutable
            generateStockMessageAndSend(stock, getSender());
        else
            unhandled(message);
        
    

    //... More code

【问题讨论】:

您根本无法在不发生可怕事情的情况下跨参与者共享可变数据。不要这样做。最好找到一种方法来分片数据,例如每只股票一个演员。 Akka 通过 Cluster Sharding 支持这一点。 【参考方案1】:

解决方案:每只股票一名演员 - 根据需要创建。

StockActor - 负责维护/更新一只股票的数据。 - 对于每个股票,应在需要时创建一个 StockActor,并在不需要/完成时杀死。

StockManagerActor 在需要时创建 StockActor 并监视它们的父级 Actor。提供其他统计信息,例如一次运行的子演员数量。

Akka 分片 Akka sharding 和 Clustering 可以让你无缝地为每只股票创建一个 actor,并在不需要时钝化它们。 Akka 负责分片功能。所以我们不必担心跑步股票演员的意外死亡。

如果您不想在崩溃期间释放演员状态,也可以使用 Akka Persistence

这里有一些链接。 Persistence Sharding

【讨论】:

这个。 Actors 应该代表/跟踪一些具有需要跟踪更改/事件并对它们做出反应的身份的项目。但是,他们应该专注于他们正在跟踪的内容的当前状态,并让历史或长期分析等事情由专门用于这些功能的工具——数据库来处理。对演员进行一点分析可能是有道理的,但它不应该试图负责报道。

以上是关于在池中跨 Akka Actor 实例共享可变数据的主要内容,如果未能解决你的问题,请参考以下文章

AKKA Actor创建

[scala] akka actor编程

Akka - 你应该创建多少个actor实例?

akka设计模式系列-actor锚定

Scala笔记整理:Actor和AKKA

Scala笔记整理:Actor和AKKA