在池中跨 Akka actor 实例共享可变数据
Sharing mutable data across Akka actor instances in a pool
我在互联网上找到的大多数 Akka material 包括许多 SO 问题都指出我们应该在处理它们的 actor 中维护相关数据。不鼓励使用锁定机制
我正在开发一个基于 Akka actors 的 Java 服务,它维护着大量的动态数据。以前我使用写时复制机制进行数据更新,但这可能会导致下一版本由于预期的更新率而出现性能问题(特别是高 GC activity)。
假设我有一个管理股票信息的演员 (StockManagerActor)。经常读取和更新股票价格。 (我更喜欢让一个单独的演员接收更新并提交它们,另一个演员在需要时读取股票价格。但我不能这样做,因为它会在不同类型的演员之间共享可变的股票数据)
所以 StockManagerActor 处理两种类型的消息。 UpdateStockMessage 和 GetStockMessage。当我们想到这个 actor 的单个实例时 运行,一切似乎都很好,因为没有数据在 actor 之间共享。
我担心如果系统中只有一个StockManagerActor 运行,当股市高度活跃时,它的收件箱可能会迅速增长。所以我想要一个 StockManagerActor 池来同时处理消息。但在这种情况下,不同的 actor 实例会并发 update/get 操作。
当 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
}
解决方案:每个股票一个演员 - 根据需要创建。
StockActor
- 负责一只股票的maintaining/updating数据。
- 对于每只股票,应在需要时创建一个 StockActor,在不需要时将其杀死 needed/done。
StockManagerActor
在需要时创建 StockActor 并监视它们的父 actor。一次提供其他统计数据,例如儿童演员的数量 运行。
Akka 分片
Akka sharding 和 Clustering 可以让你无缝地为每只股票创建一个演员,并在不需要时将它们钝化。 Akka 负责分片功能。所以我们不用担心运行股票演员的意外死亡
如果您不想在崩溃期间丢失 actors 状态,只需使用 Akka Persistence。
这里有一些链接。
Persistence
Sharding
我在互联网上找到的大多数 Akka material 包括许多 SO 问题都指出我们应该在处理它们的 actor 中维护相关数据。不鼓励使用锁定机制
我正在开发一个基于 Akka actors 的 Java 服务,它维护着大量的动态数据。以前我使用写时复制机制进行数据更新,但这可能会导致下一版本由于预期的更新率而出现性能问题(特别是高 GC activity)。
假设我有一个管理股票信息的演员 (StockManagerActor)。经常读取和更新股票价格。 (我更喜欢让一个单独的演员接收更新并提交它们,另一个演员在需要时读取股票价格。但我不能这样做,因为它会在不同类型的演员之间共享可变的股票数据) 所以 StockManagerActor 处理两种类型的消息。 UpdateStockMessage 和 GetStockMessage。当我们想到这个 actor 的单个实例时 运行,一切似乎都很好,因为没有数据在 actor 之间共享。
我担心如果系统中只有一个StockManagerActor 运行,当股市高度活跃时,它的收件箱可能会迅速增长。所以我想要一个 StockManagerActor 池来同时处理消息。但在这种情况下,不同的 actor 实例会并发 update/get 操作。 当 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
}
解决方案:每个股票一个演员 - 根据需要创建。
StockActor - 负责一只股票的maintaining/updating数据。 - 对于每只股票,应在需要时创建一个 StockActor,在不需要时将其杀死 needed/done。
StockManagerActor 在需要时创建 StockActor 并监视它们的父 actor。一次提供其他统计数据,例如儿童演员的数量 运行。
Akka 分片 Akka sharding 和 Clustering 可以让你无缝地为每只股票创建一个演员,并在不需要时将它们钝化。 Akka 负责分片功能。所以我们不用担心运行股票演员的意外死亡
如果您不想在崩溃期间丢失 actors 状态,只需使用 Akka Persistence。
这里有一些链接。 Persistence Sharding