[Erl_question11] mnesia distributed application example
Scenario:
Design a library management system. Requirements:
1. Basic addition, deletion, query, and modification functions;
2. multi-node backup is supported (one of the nodes fails and the external interface is not affected ).
Solution 1:
Erlang code: https://gist.github.com/zhongwencool/28f7db8d52134b082f97
Start shell:
erl -name [email protected]127.0.0.1 -pa "../ebin/" -setcookie best -run cloud_server start_link erl -name [email protected]127.0.0.1 -pa "../ebin/" -run deal_book_server -extra [email protected]127.0.0.1 erl -name [email protected]127.0.0.1 -pa "../ebin/" -run deal_book_server -extra [email protected]127.0.0.1
.......
erl -name [email protected]127.0.0.1 -pa "../ebin/" -run deal_book_server -extra [email protected]127.0.0.1
Tip: the key to implementation is that each node is automatically connected to the cloud center node and connected to the cloud at every 15scheck. The cloud always ensures the latest node connection status data, and periodically broadcast to all connected nodes.
If you write this example yourself, you will have a deeper understanding of node interconnectivity.
Solution 2:
Use the following mnesia distribution features:
1. First, we will implement a simple 1 + 1 (one data processing node + one backup node)
-module(db_sync). -author("[email protected]"). %% 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 ('[email protected]'), 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)}]). % view database status 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 In xterm 1:
> erl erl -sname one -mnesia dir "one"
1.2 In xterm 2:
> erl -sname two -mnesia dir "two" > db_sync:create_schema().
1.3 start mnesia in one shell and two shell respectively
> mnesia:start().
1.4 create an account table on any node
> db_sync:create_table().
Here, the account table is shared by the one and two nodes. You can add a data on the one node and query the data on the two node. For users: this is completely transparent !!
1.5 "test:
Add data on one node:
Query data on a two node:
2. After the node one fails, how can I synchronize the two data to the node one after the restart?
After the node one restarts, you can re-create the database table once. If the data changes on the node two after the one fails to restart, you can also use mnesia: add_table_copy to synchronize data.
I believe that if you have mastered the two features of mnesia, You can implement a more concise distribution system than solution 1!
Read the mnesia document and find an interesting point:
Do you think that mnesia only uses one key (of course you can use a complex match expression to implement complex query conditions), but because the efficiency of match is relatively low, if you use it frequently, it is not recommended. here you should look at the following function: You can add an index.! [Real benefits]
Add_table_index (tab, attrname)-> {aborted, r }|{ atomic, OK}
Table indices can and shocould 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 accountid 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.
Doing so is better than doing another table with the corresponding ID and name.
I personally think mnesia's source code is well written and worth further reading.