在github上,关于erlang的一致性hash,有erlang-ryng和 hash_ring .在这里先聊下erlang-ryng这个. 在erlang-ryng的启动方式上,github上提供了原始的启动方式,即直接在erlang shell下输入 erl -pa ebin -run ryng manual_start
$ erl -pa ebin -run ryng manual_start
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false] [dtrace]Eshell V5.10.3 (abort with ^G)
1> ryng:new_ring([{id, my_ring}]).
{ok,<0.47.0>}
2> ryng:add_node(my_ring, node0).
ok
3> %% weight &#61; 1: counts as 2 when there&#39;s one other node of weight 0
3> ryng:add_node(my_ring, node1, 1).
ok
4> %% weight &#61; 0, priority &#61; 1: will only be selected if priority 0 is empty
4> ryng:add_node(my_ring, node2, 0, 1).
ok
5> ryng:sync_ring(my_ring).
ok
6> ryng:node_for(my_ring, erlang:now()).
{ok,node1}
7> ryng:node_for(my_ring, erlang:make_ref()).
{ok,node1}
8> ryng:node_for(my_ring, random:uniform()).
{ok,node1}
9> ryng:list_rings().
{ok,[{ryng_ring_v1,my_ring,sha,160,#Fun
10> ryng:list_nodes(my_ring).
{ok,[{ryng_node_v1,node0,0,0},{ryng_node_v1,node1,0,1},{ryng_node_v1,node2,1,0}]}
11> ryng:balance_summary(my_ring).
{ok,[{0,node0,0.3333333333333333},{0,node1,0.6666666666666666},{1,node2,1.0}]}
12> ryng:balance_check(my_ring, 1000000).
{ok,{1000000,1281043,1.281043},[{node0,333425,0.333425},{node1,666575,0.666575}]}
13> ryng:del_node(my_ring, node1).
ok
14> ryng:sync_ring(my_ring).
ok
15> ryng:balance_summary(my_ring).
{ok,[{0,node0,1.0},{1,node2,1.0}]}
16> ryng:balance_check(my_ring, 1000000).
{ok,{1000000,1154860,1.15486},[{node0,1000000,1.0}]}
17> ryng:del_node(my_ring, node0).
ok
18> ryng:sync_ring(my_ring).
ok
19> ryng:balance_summary(my_ring).
{ok,[{1,node2,1.0}]}
20> ryng:balance_check(my_ring, 1000000).
{ok,{1000000,1157669,1.157669},[{node2,1000000,1.0}]}
21> ryng:rm_ring(my_ring).
ok
22> ryng:list_rings().
{ok,[]}
而-run ryng manual_start ,我们一般不这么用&#xff0c;而根据erlang shell的解释&#xff0c;-run Mod [Func [Arg1, Arg2, ...]](init flag) 解释为 Makes init call the specified function.
这样我们就明白了&#xff0c;使init调用这个指定函数. 而 这个ryng 模块的 manual_start 函数是干什么的呢&#xff1f;
进入代码看下:
%% &#64;doc Manually start ryng and all dependencies.
-spec manual_start() -> ok.
manual_start() ->require([crypto, ryng]).
而require/2 这个函数的作用是做什么的呢&#xff1f;
%% &#64;doc Start the given applications if they were not already started.
%% &#64;private
-spec require(list(module())) -> ok.
require([]) ->ok;
require([App|Tail]) ->case application:start(App) ofok -> ok;{error, {already_started, App}} -> okend,require(Tail).
这样就依次启动了application&#xff0c;通过尾递归实现了。 这样的写法还是不错的&#xff0c;而我们在application启动的时候&#xff0c;一般都直接添加个application启动。