erlang mnesia 節點同步資料

2021-08-02 13:01:30 字數 4195 閱讀 6136

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...