使用 gen_server 封装一个 mnesia 表?

Posted

技术标签:

【中文标题】使用 gen_server 封装一个 mnesia 表?【英文标题】:Using gen_server to encapsulate an mnesia table? 【发布时间】:2010-11-29 01:51:35 【问题描述】:

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

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

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

非常感谢任何输入。

【问题讨论】:

【参考方案1】:

我猜根据Occam's razor,没有必要存在这个gen_server,尤其是因为其中绝对没有状态存储。当您需要以严格顺序访问表(或任何其他资源)时(例如,您可能希望避免任何中止的事务在瓶颈成本)。

模块中封装对表的访问是一个很好的解决方案。它不会产生额外的复杂性,同时提供了适当的级别的抽象和封装。

【讨论】:

【参考方案2】:

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

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

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于使用 gen_server 封装一个 mnesia 表?的主要内容,如果未能解决你的问题,请参考以下文章

与 Mnesia 保持关系完整性

Erlang:Mnesia:连续更新单个字段值

是否可以使用 Erlang、Mnesia 和 Yaws 开发强大的网络搜索引擎?

集群中一个 Mnesia Master Node 的意义是啥

Mnesia 表复制/共享

何时在 Erlang/OTP 应用程序中使用 gen_server