杂项

前二章讲了如何启动数据库,如何构建数据库,接下来会为讲一些创建分布式容错数据所需的高级特征:

  • 索引
  • 分布式和容错
  • 表分段
  • 本地内容表
  • 无磁盘节点
  • 高级方案管理
  • 调用应用程序
  • 并行进程
  • 原形研究
  • 基于对象的编程

1、索引

如果数据添加索引,那位定位会很快,如果没有索引,就需要遍历表,可能会消耗较长时间。Mnesia提供了如下两个函数操作索引:

mnesia:add_table_index(Tab, AttributeName)

mnesia:delete_table_index(Tab,AttributeName)

可能通过如下函数进行索引查找:

mnesia:index_read(Tab, SecondaryKey, AttributeName) mnesia:index_match_object(Pattern, AttributeName) mnesia:match_object(Pattern)’

2、分布式和容错

mnesia提供了多种方式把表复制到多个不同的Erlang节点上。编程人员除表名不用关心表的具体在那个节点上。实现具体位置透明化。(当然如果数据在远程节点,处理会慢一点), 数据库可以反复配置, 表可以在节点间移动。这并不影响编程人员。

以下是创建一个表,带有两个复件:

    mnesia:create_table(foo,
                        [{ram_copies, [N1, N2]},
                         {attributes, record_info(fields, foo)}]).
 

表可能拥有如下类型,每个类型都可以有一个Erlang节点列表:

ram_copies,RAM复件会在每个节点上存在。可以通过mnesia:dump_table函数将RAM表保存到磁盘上。

disc_copies,表复件会在每个节点的内存和磁盘上存在。写操作会影响RAM和磁盘。

disc_only_copies,表复件只会出在各节点的磁盘上。会影响访问速度,但会节约内存。

运行时也是可以修改表属性的。使用表复件有两个原因, 容错和速度。如果我们拥有两个活动节点, 任一节点故障后,复件节点仍然可用。 此外,假如一个表存在两个节点,应用程序在任一节点上读数据而无需访问网络。网络访问意味着比本地操作低效。

对于数据经常读,而少量写的应用,表复件是非常具有优势的。劣势就是增加了写操作时间。假如一个表有两个复件,每一个写操作必需访问两个表复件。甚至其中一个写操作为网络操作。消耗比非复件表大很多。

3、表片段

 表片段主用于应对超大表。其核心就是把一个表分隔成多个可控表片段。每个片段被实现为第一级的Mnesia表,就像普通表一样,可以复件,可以索引等。但是不能拥有local_content和snmp活动连接。

mnesia提供了mnesia_frag模块, 实现了mnesia_access回调行为用于访问片该记录。

在访问记录前,mnesia_frag先计算记录键值的hash值 ,然后通过hash值确定表片段名字。最终就像普通表一样进行访问处理。如果不能预先知道记录键值, 需要在所有表片段中进行匹配。注,在ordered_set表中,记录在表片段内进行排序。select 和match_object等函数的返回结果也是无序的。如下就是展示了如何将一个现存表转换成片段表,如何添加更多表片段。

 

Eshell V4.7.3.3  (abort with ^G)
(a@sam)1> mnesia:start().
ok
(a@sam)2> mnesia:system_info(running_db_nodes).
[b@sam,c@sam,a@sam]
(a@sam)3> Tab = dictionary.
dictionary
(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
{atomic,ok}
(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
#Fun<erl_eval>
(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
ok
(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
{atomic,ok}
(a@sam)8> mnesia:table_info(Tab, frag_properties).
[{base_table,dictionary},
 {foreign_key,undefined},
 {n_doubles,0},
 {n_fragments,1},
 {next_n_to_split,1},
 {node_pool,[a@sam,b@sam,c@sam]}]
(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
#Fun<erl_eval>
(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{c@sam,0},{a@sam,1},{b@sam,1}]
(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
{atomic,ok}
(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{b@sam,1},{c@sam,1},{a@sam,2}]
(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
{atomic,ok}
(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{a@sam,2},{b@sam,2},{c@sam,2}]
(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
{atomic,ok}
(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
#Fun<erl_eval>

(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag).
[{dictionary,12,-12}]
(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag).
[{dictionary,64},
 {dictionary_frag2,64},
 {dictionary_frag3,64},
 {dictionary_frag4,64}]
(a@sam)19
 表片段属性

可以能过mnesia:table_info(Tab, frag_properties).取得表性能, 其中有如下属性:

{n_fragments, Int}表上有多少片段

{node_pool, List}

{n_ram_copies, Int}

{n_disc_only_copies, Int}

{foreign_key, ForeignKey}

{hash_module, Atom}

表片段管理

 mnesia:change_table_frag(Tab,  Change)  用作重新配置片段表。可以有如下参数:

 {activate, FragProps}激活现存表的片段属性

deactivate  停止片段属性

{add_frag, NodesOrDist}添加一个新片段

del_frag删除 一个片段

{add_node, Node}添加一个新节点到节点池。

{del_node, Node}从节点池删除一节点

扩展忆存在的函数

函数 mnesia:create_table/2 通过指定 frag_properties 属性创建片段表。

 mnesia:delete_table/1 删除片段表,并删除所有片段。

  mnesia:table_info/2能够取出所有frag_properties 项目。

负载平衡

在做负载平衡可能要注意以下情况:

节点发生永久变化, 如节点添加或者移除,此时可能要变化节点池。也可能引起表片段发生变化,进行重新分配。

内存使用超过阀值,此时也许要重新考虑添加表片段等。

临时节点故障,这种情可能可能需要添加些复件,用于冗余 。

4、本地内容表

复件表拥有相同内容在所有节点上,有时要可能需要各个节点保存不一样的数据。当我们创建表时指定属性{local_content, true},表存在于我们指定的节点上存在, 所有操作仅在本地备份上。另外,我们在启动时,只初始化本地版本,不会与会远端节点进行同步。

5、无磁盘节点

 可以在无磁盘节点上运行mnesia, 当然不能在这些节点上运行disc_copies,disc_only_copies类型的节点, 所有mnesia启动自己需要的schema表会比较麻烦。

shema表像其它表一样,存在于一个或多个节点上,它的存储类型是disc_copies或者ram_copies(不可为disc_only_copies).在启动mnesia方案的时候,确定了哪些节点需要建立联系,如果有任何其它节点已经启动了,就从已经已经启动了节点取得表定义与本地的进行合并。参数extra_db_nodes就是用于指定节点列表。

所以,当一个无磁盘节点需要从网络的远端节点上找到一个方案定义 , 我们应该提供节点列表信息,参数如:-mnesia extra_db_nodes NodeList。对于没有进行配置指定的, mnesia会作为一个单节点系统启动, 也可以通过使用mnesia:change_config/2重置'extra_db_nodes',强制连接。

6、更多方案管理

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2011-12-26 09:43  陈峰  阅读(2507)  评论(0编辑  收藏  举报