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