如何在部署在不同集群节点上的两个相同参与者之间保持状态?(akka.net)



如果我有下面这样的设置,假设我将有3个节点加入一个集群,并且我使用循环池。

var worker = cluster.ActorOf(Props.Create<Worker>().WithRouter(
                 new ClusterRouterPool(
                     new RoundRobinPool(5),
                     new ClusterRouterPoolSettings(30, true, 1))), "worker");

"工作人员"只记得它处理了多少条信息,就像下面的一样

public class Worker : TypedActor, IHandle<int> {
readonly List<int> processed;
public Worker()
{
    processed = new List<int>();
}
public void Handle(int message)
{
    System.Threading.Thread.Sleep(new Random().Next(1000, 2000));
    processed.Add(message);
    Console.WriteLine("WORKER ({0}) [{1}:{2}], processed: {3}", message, Context.Self.Path, Cluster.Get(Context.System).SelfUniqueAddress.Address.Port, processed.Count);
}

是否有任何方法可以在不同集群节点上的不同参与者之间同步"已处理列表"?这是akka.net.cluster.sharding最终会做的事情吗?还是我在做一些完全没有意义的事情?

一般来说,您的问题似乎最接近JVM akka eventuate和ddata插件所提供的。在每种情况下,当参与者在同一条数据上处理它时,通常的副作用是最终的一致性——因为你的状态在多台机器上工作的许多参与者之间是"共享的",所以在特定时间点的实际状态可能会模糊,并且会根据你将采取的参与者的观点而有所不同。

目前,我还没有听说.NET平台上有任何适合您的成品选项,但Akka.DistributedData(目前正在开发中)将允许您完成任务。这是CRDT的Akka实现。

CRDT将为您提供对最终一致的数据类型的访问,这些数据类型可以在分布式集群中的不同节点上复制,直到整个应用程序的总体状态简洁为止。在这种情况下,您可以将processed列表替换为GSet,这将允许您以分布式方式将元素附加到一个数据集。

如果您不想等待、冒险或自行构建CRDT,您可以使用Riak等第三方解决方案。

PS:Akka.Cluster.Sharding有一个不同的目的,那就是即使节点数量发生变化,也会自动在集群上平均分配参与者,以便在当前集群范围内只存在一个特定参与者的实例

最新更新