在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 = 1: counts as 2 when there's one other node of weight 0 3> ryng:add_node(my_ring, node1, 1). ok 4> %% weight = 0, priority = 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<ryng.2.107634887>, 1461501637330902918203684832716283019655932542976, [{0,487167212443634306067894944238761006551977514325}, {1,1461501637330902918203684832716283019655932542976}], [{0,3},{1,1}], 16402,20499,true,undefined}]} 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 ,我们一般不这么用,而根据erlang shell的解释,-run Mod [Func [Arg1, Arg2, ...]](init flag) 解释为 Makes init call the specified function.
这样我们就明白了,使init调用这个指定函数. 而 这个ryng 模块的 manual_start 函数是干什么的呢?
进入代码看下:
%% @doc Manually start ryng and all dependencies. -spec manual_start() -> ok. manual_start() -> require([crypto, ryng]).
而require/2 这个函数的作用是做什么的呢?
%% @doc Start the given applications if they were not already started. %% @private -spec require(list(module())) -> ok. require([]) -> ok; require([App|Tail]) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end, require(Tail).
这样就依次启动了application,通过尾递归实现了。 这样的写法还是不错的,而我们在application启动的时候,一般都直接添加个application启动。