[Erlang12] Mnesia分布式应用

[Erl_Question12] Mnesia分布式应用

情景:

设计一个图书管理系统,需求:

1. 基本的增删查改功能;

2. 支持多节点备份(其中一个节点挂了进,对外接口不影响)。

方案一:

image_thumb2

Erlang 代码如下:https://gist.github.com/zhongwencool/28f7db8d52134b082f97

启动shell:

   erl -name cloud_server@127.0.0.1 -pa "../ebin/" -setcookie best -run cloud_server start_link 
   erl -name server0@127.0.0.1 -pa "../ebin/" -run deal_book_server -extra server0@127.0.0.1 
   erl -name server1@127.0.0.1 -pa "../ebin/" -run deal_book_server -extra server1@127.0.0.1
   ....... 
   erl -name server9@127.0.0.1 -pa "../ebin/" -run deal_book_server -extra server9@127.0.0.1 

Tip: 实现的关键在于:每个节点起来后会自动连接到Cloud Center Node 上,并在每15scheck一下与Cloud的连接,Cloud时刻保证最新了节点连接状态数据,并定时广播给连上来的所有节点。

如果你自己写完这个例子,就会对节点互接有更深认识。

方案二:

使用Mnesia的分布特性:

1. 首先我们来实现一个简单的1+1(一个数据处理节点 + 一个备份节点)

 
   -module(db_sync).
   -author("zhongwencool@gmail.com").

   %% API
   -export([create_schema/0, create_table/0,i/0]).
   -export([add_account/3,del_account/1,read_account/1]).
   -record(account, {id = 0, name = "", phone = 138000001}).

   create_schema() –>
      net_kernel:connect('two@E7D4C9EFE9C405'),
      io:format("Self:~w,Connect Nodes:~w",[node(),nodes()]),
      mnesia:create_schema([node()|nodes()]).

   create_table() –>
     mnesia:create_table(account,
         [{disc_copies,[node()|nodes()]},
             {attributes,
                 record_info(fields, account)}]
      ).

   %%查看数据库状态
  i() –>
      mnesia:system_info().

  add_account(ID, Name, Phone) –>
      mnesia:transaction(
          fun() –>
              mnesia:write(#account{id = ID, name = Name, phone = Phone})
          end).
  del_account(ID) –>
      mnesia:transaction(
          fun() –>
              mnesia:delete({account, ID})
          end).
  read_account(ID) –>
      mnesia:transaction(
          fun() –>
              mnesia:read({account, ID})
          end).

1.1 在xterm 1中:

 > erl erl -sname one -mnesia dir "one"

1.2 在xterm 2中:

 > erl -sname two -mnesia dir "two"
 > db_sync:create_schema().

1.3 分别在one shell ,two shell中启动mnesia

 > mnesia:start().

1.4 在任意节点中创建account表

> db_sync:create_table().

这里的account表就是one , two 节点所共享的了,你可以在节点one上增加一个数据,在节点two上查询这个数据,对于用户来说:这完全是透明的!!

1.5 Test:

one 节点上增加数据:

image_thumb21

two 节点上查询数据:

image_thumb4

2. 节点one挂了后,重启怎么把从two数据同步到节点one?

节点one重启后把数据库表重新建一次就可以啦,如果数据在one挂掉至重启过程中在节点two上发生了变化了,也可以使用mnesia:add_table_copy来做到数据同步。

相信如果掌握了mnesia这2个特性,就可以实现比方案一更加简洁的分布系统啦!


看Mnesia文档里发现一个有意思的点:

是不是觉得mnesia只有使用一个key(当然你可以使用复杂的match表达式来做实现复杂查询条件),但因为match的效率比较低,所有如果你频繁的使用,是不推荐的,这里你应该看看下面这个函数:可以增加一个index哦!【真福利】

add_table_index(Tab, AttrName) -> {aborted, R} | {atomic, ok}

Table indices can and should be used whenever the user wants to frequently use some other field than the key field to look up records. If this other field has an index associated with it, these lookups can occur in constant time and space. For example, if our application wishes to use the name field of accountto efficiently find all account with a specific name, it might be a good idea to have an index on the namefield. This can be accomplished with the following call:

mnesia:add_table_index(account, name).
Indices do not come free, they occupy space which is proportional to the size of the table. They also cause insertions into the table to execute slightly slower.
这样做总比再做一张表来对应Id和Name好多了。
 
个人觉得Mnesia的源码写得真好,值得精读.
      image_thumb7        
------------------------------------------------------------------------------------------------------------------
                
  一个男人背后的心酸,是旁人无法想象的
  
posted @ 2014-07-20 15:57  写着写着就懂了  阅读(1654)  评论(0编辑  收藏  举报