2009-09-17 52 views
8

我有一个在Erlang制作的服务器应用程序。其中我有一个mnesia表 ,存储一些照片信息。本着“一切都是 过程”的精神,我决定将该表包装在gen_server模块中,以便 gen_server模块是唯一直接访问该表的模块。查询 并向该表添加信息是通过向该进程 (其具有注册名称)发送消息来完成的。这个想法是将有几个客户端进程查询来自该表的信息。使用gen_server封装mnesia表?

这工作得很好,但gen_server模块没有状态。它所要求的一切都存储在mnesia表中。所以,我想知道gen_server可能不是封装该表的最佳模型吗?

我是不是应该让它成为一个进程,而只是通过该模块中的函数封装表 ?如果该模块中存在错误,那么 会导致调用进程崩溃,我认为这可能会更好,因为 它只会影响单个客户端,而不是现在,这会导致进程到达 gen_server进程导致每个人都无法访问表格(直到主管重新启动 ))。

任何输入,非常感谢。

回答

9

我想根据Occam's razor没有必要为此gen_server存在,特别是因为有绝对未存储状态。当您需要访问表(或任何其他资源)为严格顺序(例如,您可能想要避免以瓶颈为代价的任何中止事务)时,可能需要此过程。

模块中封装对表格的访问是一个很好的解决方案。它创建了没有额外的复杂性,同时提供适当的水平的抽象和封装。

6

我不确定我明白你为什么决定用一个进程封装一个表。 Mnesia旨在调解多个并发访问表,无论是在本地还是分布在一个集群中。

创建一个执行所有特定表访问操作和更新的API模块是一个好主意,因为API函数会更好地在调用它们的代码中传达您的意图。它比将mnesia操作直接放入调用代码更具可读性。

如果需要,API模块还可以让您在以后从mnesia切换到其他存储系统。在你的API模块中使用mnesia事务可以保护你免受一些程序错误的困扰,因为mnesia会回滚崩溃的操作。 API模块将始终可供调用者使用,并允许任意数量的调用者同时执行操作,而基于gen_server的API具有可导致API不可用的失败点。

基于gen_server API通过纯功能性API提供的唯一功能是序列化对表的访问 - 这是一个不寻常的要求,除非您特别需要它,否则它将成为性能杀手。

0

当您想使用脏访问并避免事务时,使用单个gen_server进程处理mnesia表可能是一个好主意。这种方法可能比txs更快,但通常你需要对它进行基准测试。