gpt4 book ai didi

erlang - 如何保证Erlang集群中进程的唯一性?

转载 作者:行者123 更新时间:2023-12-02 05:46:47 26 4
gpt4 key购买 nike

我正在尝试找出解决 Elixir 应用程序的以下负载分配/进程唯一性保证问题的最佳方法。

应用程序

我的 Elixir 应用程序在 n 个不同节点(从大型池中随机选择,没有预先已知的固定 IP 或主机名)上启动,形成一个集群(我不确定最好的方法是什么)节点发现尚未完成,但我们暂时忽略它)。

简而言之,该应用程序的主要目的是使两个系统随着时间的推移保持同步,基本上是一种集成。每个用户都有一个集成,可以随时添加新的集成或删除现有的集成。

问题

我希望每个集成都有一个 Erlang 进程,因为它在概念上非常优雅并带来许多好处(例如为每个集成提供一个自然的同步点)。这似乎也是扩展系统的方法。

问题是,显然这个过程在整个集群中必须是唯一的(如果两个进程尝试同步相同的集成,则很难预测数据可能会发生什么),并且我想将工作自动重新分配为节点失败或出现新的集成。

此外,在部署新版本的应用程序时,新集群会在旧集群关闭之前启动(我们不依赖于热代码重新加载)。这个过渡阶段需要以某种方式处理。

可能的解决方案

一种解决方案可能是依赖全局流程。启动时,节点会自行注册,连接到其他已注册的节点,然后尝试启动其全局 Scheduler 进程的副本,该进程的唯一作用是启动跨节点的集成进程。

虽然这提供了容错能力,但它并不能保证每个集成都有一个进程,因为集群可以通过网络分区分成两个。它也无法处理新旧集群都在线并且旧集群仍在工作的短暂时期。

某种全局锁定机制(通过共享的 Redis 实例?)可用于处理网络分区和应用程序重新启动,但这看起来相当hacky。

有什么建议吗?

谢谢!

最佳答案

出于解释的目的,我们假设:

  • 每个用户都由一个在整个系统中唯一的 ID 来标识 - UID
  • 每个进程都由一个节点上唯一的 ID 来标识 - PID
  • 每个节点都由跨节点唯一的 ID 进行标识 - NID
  • 每个用户的集成器进程由元组 {NID, PID}
  • 标识

问题在于确保UID{NID, PID}之间存在1对1映射。

解决这个问题基本上有两种方法:

。引入一个共享状态,类似于寄存器,它跟踪 UID{NID, PID} 之间的映射。我们称之为登记册。如果这是一个具有共享模式的 mnesia 数据库,那么 Redis 实例、单独的节点或其他任何东西都是实现细节。无论如何,每个新进程都需要在开始集成特定 UID 之前在 The Register 中注册。如果出现网络分区、节点宕机或其他灾难,您可以按照标准方式处理,例如您使用适当的 CAP theorem 来设计登记册根据您的要求考虑。

。通过算法将给定 UIDPID 分配给 NID。这与hashtable类似。 。举个例子,假设 UID 是一个整数(如果不是,那么任何数据结构都可以通过 hash function 简化为整数)。您选择这样的节点:

NID = UID % NX

其中 NX 是节点数量(% 当然是 modulo operation )。在每个节点上,您可以将进程注册为UID。完成后,您可以根据 UID 唯一地处理每个集成器进程 - 您可以使用 % 操作来获取 NIDUID 本身来获取节点上的PID

第二种方法要求节点数量不变,例如节点受到监控,如果一个节点出现故障,另一个节点就会启动来取代它。它还可以将每个节点作为主从对,并在它们之间进行一些复制。

这两种方法之间的区别在于,在第一种情况下,您会遇到单点故障 - 如果寄存器不可用,则无法启动新的集成器。而在第二种情况下,UID 及其集成器进程之间的分配是完全分布式和异步的 - 如果一个节点发生故障,其他节点将不间断地工作,这使得扩展变得更容易。

但是,如果节点数量发生变化,第一种方法仍然像以前一样工作,而在第二种方法中,这也会导致哈希函数发生变化。这需要重新平衡进程(在节点之间移动),以便仍然可以正确处理它们。

关于erlang - 如何保证Erlang集群中进程的唯一性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35491952/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com