使用gen_server封装mnesia表?

时间:2009-09-17 08:28:47

标签: erlang mnesia otp

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

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

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

非常感谢任何输入。

3 个答案:

答案 0 :(得分:10)

我想根据Occam's razor不需要存在gen_server ,特别是因为其中存储了绝对无状态 。当您需要访问表(或任何其他资源)严格顺序时,可能需要此类过程(例如,可能希望避免任何中止的事务处理瓶颈成本)。

封装对模块中表格的访问是一个很好的解决方案。它会创建没有额外的复杂性,同时提供正确的级别的抽象和封装。

答案 1 :(得分:6)

我不确定我理解为什么你决定用进程封装表。 Mnesia旨在调解对表的多个并发访问,包括本地和分布在集群中。

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

如果需要,API模块还为您提供了从mnesia切换到其他存储系统的选项。在API模块中使用mnesia事务可以保护您免受某些编程错误的影响,因为mnesia将回滚崩溃的操作。 API模块始终可供调用者使用,并允许任意数量的调用者同时执行操作,而基于gen_server的API有一个失败点,该过程可以使API不可用。

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

答案 2 :(得分:0)

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