mnesia的機制稍微有些奇怪, 今天一天都比較閒,於是測試study了下, 看看是如果動作.
目標:
逐漸新增n個mnesia節點,並確保資料在這些節點上保持同步.
過程如下:
1. mnesia的分布式可以從乙個節點開始, 然後慢慢新增.
2. 新增加乙個節點的時候, 首先要確保新節點上已經呼叫過mnesia:start()
3. 在每個已知存活的節點上呼叫(可以用rpc:call)mnesia:change_config(extra_db_nodes, [newnode]),這樣可以通知每個節點, 有乙個新的節點要加入進來了
4. 改變newnode上的schema表的儲存方式: mnesia:change_table_copy_type(schema, newnode, disc_copies)
5. 重啟動newnode的mnesia,並稍微等待一段時間.(這大概是由於遠端新節點的schema改變後,不能及時反應的緣故,可能不是必要的)
6. 向newnode追加tablelist : mensia:add_table_copy(table, newnode, disc_copies), 這裡可能會呼叫多次,有多少使用者表,就呼叫多少次
---- over all ----
上面的6步可以確保依次增加新的節點並確保資料同步.
對應的**如下:
erlang**
addnode(newnode) ->
io:format("new node = ~p~n"
, [newnode]),
runningnodelist = mnesia:system_info(running_db_nodes),
io:format("-----------adding extra node---------~n"
),
addextranode(runningnodelist, newnode),
io:format("-----------chang schema -> disc_copies---------~n"
),
rtn = mnesia:change_table_copy_type(schema, newnode, disc_copies),
io:format("rtn=~p~n"
, [rtn]),
io:format("-----------reboot remote node mnesia---------~n"
),
rpc:call(newnode, mnesia, stop, ),
timer:sleep(1000
),
rpc:call(newnode, mnesia, start, ),
timer:sleep(1000
),
io:format("-----------adding table list---------~n"
),
addtablelist(?tablelist, newnode),
io:format("-----------over all---------~n"
).
addextranode(, _newnode) ->
null;
addextranode(_runningnodelist = [node | t], newnode) ->
rtn = rpc:call(node, mnesia, change_config, [extra_db_nodes, [newnode]]),
io:format("node = ~p, rtn=~p~n"
, [node, rtn]),
addextranode(t, newnode).
addtablelist(, _newnode) ->
null;
addtablelist(_tablelist = [table | t], newnode) ->
rtn = mnesia:add_table_copy(table, newnode, disc_copies),
io:format("table = ~p, rtn = ~p~n"
, [table, rtn]),
addtablelist(t, newnode).
額外的, 可能會有這種情況, 乙個a節點可能已經斷開了,然後乙個新的b節點被追加了進來, 這個時候如果a節點在上線,可能檢測不到b節點其實是於自己保持同步的,這樣有可能造成資料不同步, 解決該問題的方法即呼叫net_adm:ping(node) :即每乙個新節點上線後,即mnesia:start()以後, 立即查詢與自己相連線的節點(mnesia:system_info(db_nodes)),然後用net_adm:ping()去ping下每乙個連線的node,告訴自己上來了,這樣即可解決剛才的問題.
對應的**如下:
erlang**
-module(ping).
-compile(export_all).
ping() ->
case whereis(ping) of
undefined ->
null;
oldpid ->
oldpid ! ,
unregister(ping)
end,
pingid = spawn(?module, pingmain, ),
register(ping, pingid),
pingid.
pingmain() ->
allnodelist = mnesia:system_info(db_nodes),
pinglist(allnodelist),
nodelistcount = length(allnodelist),
receivemsg(0, 0
, nodelistcount).
receivemsg(pingok, pingfailed, nodelistcount) ->
receive
->
case result of
true ->
newpingok = pingok + 1
, newpingfailed = pingfailed;
false ->
newpingok = pingok,
newpingfailed = pingfailed + 1
end,
case (newpingok + newpingfailed
true ->
receivemsg(newpingok, newpingfailed, nodelistcount);
false ->
io:format("-------ping over---------~n"
),
io:format("ping ok = ~p~n"
, [newpingok]),
io:format("ping failed = ~p~n"
, [newpingfailed])
end;
->
io:format("receive to exit~n"
);
_any ->
receivemsg(pingok, pingfailed, nodelistcount)
after 30000
->
io:format("error : time out~n"
) end.
pinglist() ->
null;
pinglist(_nodelist = [node | t]) ->
spawn(?module, pingone, [node]),
pinglist(t).
pingone(node) ->
rtn = net_adm:ping(node),
pingid = whereis(ping),
case rtn of
pong ->
pingid ! ;
pang ->
pingid !
end.
Erlang Mnesia資料庫遷移方法
本文參考 因為一些原因,需要把乙個mnesia節點的資料庫搬遷到另乙個節點,然後棄用原來的節點。首先假設節點a a ipa 需要搬遷到節點b b ipb 它們需要能夠連通 a ipa 需要啟動著 包括mnesia,set cookie cookiea 啟動節點b,為mnesia指定乙個新路徑 erl...
centos7 配置各從節點與主節點時間同步
chrony是乙個ntp協議的實現程式,既可以當做服務端,也可以充當客戶端 它專為間歇性網際網路連線的系統而設計,當然也能良好應用於持久網際網路連線的環境 chrony有三個時間參考 硬體時鐘 實時時鐘以及手動同步。yum install chrony yvim etc chrony.conf暫時只...
erlang mnesia資料庫設定主鍵自增
mnesia是erlang otp自帶的分布式資料庫管理系統。mnesia配合erlang的實現近乎理想,但在實際使用當中差強人意,總會有一些不足。mnesia資料表沒有主鍵自增的功能,但在mnesia函式中有乙個自增函式可以用來生成自增的id,在後面的內容將講述如何實現主鍵自增的功能。參照sqli...