我有一个在Erlang中制作的服务器应用程序。在其中我有一张mnesia表
存储一些照片信息。本着“一切都是
进程“我决定将该表包装在gen_server
模块中,以便...
gen_server
模块是唯一直接访问该表的模块。查询
并通过向该进程发送消息来向该表添加信息
(已注册名称)。这个想法是会有几个客户
进程查询该表中的信息。
这很好用,但gen_server
模块没有状态。一切都好
要求存储在mnesia表中。所以,我想知道是否gen_server
不是封装该表的最佳模型吗?
我应该简单地不将其作为一个过程,而只是封装表格
通过该模块中的功能?如果该模块中存在错误,那就是
会导致调用进程崩溃,我认为可能会更好,因为
它只会影响一个客户,而不是现在,当它会导致
gen_server
进程崩溃,让每个人都无法访问该表(直到
主管重启它。)
非常感谢任何输入。
答案 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更快,但通常你需要对它进行基准测试。