`
20.Shadow
  • 浏览: 4891 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Erlang - 分布式的Mnesia学习记录

阅读更多
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步可以确保依次增加新的节点并确保数据同步.
对应的代码如下:
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,告诉自己上来了,这样即可解决刚才的问题.

对应的代码如下:
-module(ping).
-compile(export_all).

ping() ->
	case whereis(ping) of
		undefined ->
			null;
		OldPid ->
			OldPid ! {exit},
			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
		{ping, Result} ->
			case Result of
				true ->
					NewPingOK = PingOK + 1,
					NewPingFailed = PingFailed;
				false ->
					NewPingOK = PingOK,
					NewPingFailed = PingFailed  + 1
			end,
			case (NewPingOK + NewPingFailed < NodeListCount) of
				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;
		{exit} ->
			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 ! {ping, true};
		pang ->
			PingID ! {ping, false}
	end.


------------------------------------------------
题外话,erlang的编译器比较怪,我在WinXP上面如果使用类似-record定义,然后使用%%-comment的话,就会报告错误@__@...... 因此上述的代码均没有注释...哪位好心人如果知道请告诉我下这个是为撒,Thanks~~
1
0
分享到:
评论
2 楼 aiquantong 2013-01-02  
3. 在每个已知存活的节点上调用(可以用rpc:call)mnesia:change_config(extra_db_nodes, [NewNode]),这样可以通知每个节点, 有一个新的节点要加入进来了  
应该是 通知互联erl节点网络中一个节点就可以了
不需要每个把??
1 楼 aiquantong 2013-01-02  
我是在 windows 下有eclipse 开发的  但是编译是在linux环境中 没有问题的啊

相关推荐

    lbm_kv:使用Mnesia构建的动态分布式,高可用性,分区容忍的内存中键值存储

    该应用程序的主要目标之一是使开发人员无需探索复杂的背景即可享受分布式Mnesia的乐趣。 因此, lbm_kv提供了原始API以及代码来处理和解决与分布式Mnesia相关的肮脏细节和pitfal。为什么要使用它? Mnesia是功能...

    Erlang编程指南

    “即便我已经使用Erlang多年,在编程的..., • 学习Erlang的跟踪机制以调试并发和分布式系统。, • 使用内置的Mnesia数据库和其他表存储功能。, 《Erlang编程指南》每章末尾都提供了练习题,并且由简单的示例贯穿全书。

    erlang mnesia 数据库基本查询

    Mnesia是一个分布式数据库管理系统,适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,越来越受关注和使用,但是目前Mnesia资料却不多,很多都只有官方的用户指南。下面的内容将着重说明 如何做 Mnesia ...

    Mnesia用户手册.zip

    Mnesia是一个分布式数据库管理系统(DBMS),适合于电信和其它需要持续运行和具备软实时 特性的Erlang应用。

    Mnesia用户手册

    Mnesia是一个分布式数据库管理系统(DBMS),适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,是构建电信应用的控制系统平台——开放式电信平台(OTP)的一部分。

    Mnesia用户手册 4.4.10版.rar

    Mnesia是一个分布式数据库管理系统(DBMS),适合于电信和其它需要持续运行和具备软实时特性的Erlang应用。 目 录 1 、介绍 . . .. . .. . . .. . 4 1.1 关于 Mnesia . . .. . .. . . .. . 4 1.2 Mnesia ...

    mykv:用ErlangOTP编写的分布式键值存储

    关于Mykv是用Erlang / OTP编写的分布式键/值存储。 它使用Mnesia作为后端。 这个应用程式是为学习目的而建立,不适合在生产应用程式中使用。建造Mykv使用 。 $ git clone https://github.com/ferigis/mykv.git$ cd ...

    备忘录:Mnesia分布式数据库的简单+强大接口

    备忘录:Mnesia分布式数据库的简单+强大接口

    Elixir程序设计语言.pdf

    2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 2.14 3.1 3.2 3.3 3.4 4.1 4.2 4.3 和Erlang互操作 错误处理 可执⾏⽂件 并发OTP并发 OTP Supervisors OTP 分布式 元编程 Umbrella Projects ...

    dbfs:基于分布式区块链的文件存储:satellite_antenna:

    Elixir中基于分布式区块链的文件存储 :satellite_antenna: DBFS是一项在Elixir中使用区块链实现(非常幼稚)分布式文件存储服务的实验。 随着人们对区块链和加密货币的兴趣日益浓厚,我想了解区块链的复杂内部工作...

    n2o::hollow_red_circle:N2O:分布式应用程序服务器

    核心功能目的:高性能协议中继端点:WebSocket,MQTT,TCP 代码库:700 LOC(Erlang),500 LOC(JavaScript) 透析仪:REBAR,REBAR3,MAD,MIX 主机:COWBOY,EMQ,MOCHIWEB,RING,TCP,UDP协议扩展模板:DTL,...

Global site tag (gtag.js) - Google Analytics