Erlang 在Elixir中创建多进程缓存

Erlang 在Elixir中创建多进程缓存,erlang,elixir,Erlang,Elixir,我在7周内阅读了7个并发模型,作者要求实现 根据需要在多个参与者之间分发缓存项的缓存 一个散列函数。创建启动多个缓存的管理器 参与者并将传入消息路由到相应的缓存工作进程。 如果其中一个缓存工作者 失败 当一个进程失败时,主管只能得到它的pid。仅使用pid,我无法理解哪个bucket需要新流程。我可能可以创建第二个映射pid->bucket\u index,但它看起来很难看 当我生成一个进程时,我能以某种方式附加其他属性吗?当进程退出时,我可以读取这些属性吗 解决这个问题的最佳方法是什么(没有O

我在7周内阅读了7个并发模型,作者要求实现

根据需要在多个参与者之间分发缓存项的缓存 一个散列函数。创建启动多个缓存的管理器 参与者并将传入消息路由到相应的缓存工作进程。 如果其中一个缓存工作者 失败

当一个进程失败时,主管只能得到它的
pid
。仅使用pid,我无法理解哪个bucket需要新流程。我可能可以创建第二个映射
pid->bucket\u index
,但它看起来很难看

当我生成一个进程时,我能以某种方式附加其他属性吗?当进程退出时,我可以读取这些属性吗

解决这个问题的最佳方法是什么(没有OTP)

这种实现也使得管理者过于“聪明”。据我所知,主管应该简单,只关心重新启动失败的进程


我不知道如何将重新启动和路由逻辑分为两个独立的进程:当主管重新启动某个进程时,路由器应该意识到这一点,并拥有最新的
PID

我认为推荐使用两个映射。“使用Erlang/OTP设计可伸缩性”中的一个示例将类似的pid整数映射存储在两个名为
msisdn2pid
pid2msisdn
的ETS表中(如果您有副本,请参见第45页),我认为这个广告软件看起来很难看,你应该考虑一下Erlang <代码>管理员<代码>,这将为你做这件事。关于命名,我认为简单的
寄存器(list到atom(integer到list(Id))
是最好的起点
defmodule CacheSupervisor do
  def start(number_of_caches) do
    spawn(__MODULE__, :init, [number_of_caches])
  end

  def init(number_of_caches) do
    Process.flag(:trap_exit, true)

    pids = Enum.into(Enum.map(0..number_of_caches-1, fn(id) ->
                                         {id, Cache.start}
                                     end), %{})

    loop(pids, number_of_caches)
  end

  def loop(pids, number_of_caches) do
    receive do
        {:put, url, page} -> send(compute_cache_pid(pids, url, number_of_caches), {:put, url, page})
                            loop(pids, number_of_caches)
        {:get, sender, ref, url} -> send(compute_cache_pid(pids, url, number_of_caches), {:get, sender, ref, url})
                                    loop(pids, number_of_caches)
        {:EXIT, pid, reason} -> IO.puts("Cache #{pid} failed with reason #{inspect reason} - restarting it")
                                loop(repair(pids, pid), number_of_caches)
    end
  end

  def restart(pids, pid) do
    #not clear how to repair, since we don't know the index of the failed process
  end

  def compute_cache_pid(pids, url, number_of_caches) do
    pids[rem(:erlang.phash2(url), number_of_caches)]
  end
end