erlang refs在节点/ VM重启之间是唯一的吗?

Nik*_*pov 6 erlang uuid ref

文档说

make_ref() -> ref()  
Run Code Online (Sandbox Code Playgroud)

返回一个几乎唯一的引用.

返回的参考将在大约2 82次呼叫后重新发生; 因此它具有足够的实用性.

但我的眼睛告诉我,在VM重启之间,我可以轻松得到相同的参考:

[~] erl
Erlang R14B04 (erts-5.8.5)
1> make_ref().
#Ref<0.0.0.33>
2> make_ref().
#Ref<0.0.0.37>
^C

[~] erl
Erlang R14B04 (erts-5.8.5)
1> make_ref().
#Ref<0.0.0.33>
Run Code Online (Sandbox Code Playgroud)

那么,Erlang的Refs有多独特呢?当标记在mq或db中持久存在并且可能由不同的VM会话生成时,它们是否适合用作唯一的"标记"生成器.

我知道UUID可以用于此.众所周知,pids()是可重复的,可重用的,如果是序列化的,则绝不是唯一的,然后从持久存储加载.

问题是,什么是refs() - 更像是UUID或更像pids()?节点之间的refs()是否唯一?重启之间?有关于这个主题的官方信息吗?

Rob*_*loi 6

与节点名称相关的引用并不意味着随机性,只是唯一性.正如您已经注意到的那样,它们是以循环方式创建的.此外,您对事实引用的正确性仅在节点的生命周期中是唯一的.一旦重启VM,就可以重复引用.

与PID的情况一样,打印的引用#Ref<W.X.Y.Z>包含 - 作为它们的第一个元素(W) - 有关节点号的信息:

erl -sname right
Erlang R15B (erts-5.9) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9  (abort with ^G)
(right@mars)1> register(right, self()).
true
(right@mars)2> receive M -> M end.
#Ref<6793.0.0.41>
(right@mars)3> 

erl -sname left
Erlang R15B (erts-5.9) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9  (abort with ^G)
(left@mars)1> {right, 'right@mars'} ! make_ref().
#Ref<0.0.0.41>
(left@mars)2> 
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下W,引用是如何在0本地节点中,6793在远程节点中.


gle*_*ber 5

在任何分布式系统中,为了能够生成唯一标识符,您必须依赖具有持久存储的中央原子ID生成器,或者确保在任何时间点正确配置集群.下面是第二种情况的一个例子.

在分布式Erlang集群{node(), now()}中可以认为是唯一的.如果您可以确保您的时钟配置合理,并且您不会启动具有相同名称的两个节点,则可以尝试使用{node(), now(), make_ref()},这将使碰撞的可能性可以忽略不计.