我有一个当前在四个节点上运行的erlang应用程序,其中包含一个复制的mnesia db,它存储有关已连接客户端的最少数据。 mnesia复制过去一直在无缝工作(据我所知),但是客户最近注意到其中一个节点缺少与他的应用程序相关的一些ID。
我不确定这是怎么发生的。我们的网络当时可能已经打了个嗝。也许?但是,目前更紧迫的是使数据在所有节点上都处于良好状态。有没有办法告诉mnesia从已知良好的节点复制?
答案 0 :(得分:3)
Mnesia对这个问题很有传奇色彩。这是一个巨大的PITA。
从CAP定理的角度来看,大多数使用Mnesia构建的系统最终都是C-A(一致性 - 可用性,没有分区容差)系统。在大多数情况下,你拥有(并严重依赖)其坚硬的一致性。然后发生网络分区...... 它仍可用于写入,但这些写入会破坏一致性。后来,Mnesia没有自动数据修复机制。
在群集中使用Mnesia的每个人都应该熟悉这些权衡。你的问题是一个明显的迹象,即使用Mnesia是一个糟糕的选择。如果这些数据对您至关重要,请加倍。
我也是以这种方式使用Mnesia(有时我们都需要你知道的速度)。但我确保只使用它来存储我可以轻松重建的数据。一般来说,如果你需要将它存储在磁盘上,除了玩具项目之外,Mnesia并不好。
我确保手头始终有这个功能:
reinit_mnesia_cluster() ->
rpc:multicall(mnesia, stop, []),
AllNodes = [node() | nodes()],
mnesia:delete_schema(AllNodes),
mnesia:create_schema(AllNodes),
rpc:multicall(mnesia, start, []).
仅在解析网络分区并且所有节点均可访问后才使用它。这将删除所有Mnesia复制品并重新启动它。再说一次,如果你不能忍受它的作用,那么使用Mnesia是一个糟糕的选择。
对于需要硬一致性的重要数据,请使用SQL。对于需要可用性的重要数据,请使用Riak。对于需要速度的共享状态,请使用Redis。 Mnesia不是这些系统的替代品,尽管起初看起来确实如此。
2014-11-16编辑:这是一篇关于这个主题的更好的文章,详细解释了我上面所说的https://medium.com/@jlouis666/mnesia-and-cap-d2673a92850
答案 1 :(得分:0)
老实说,我认为让一个不同步的Mnesia从一个已知的好节点复制的最简洁方法是关闭坏节点上的应用程序,并删除其所有Mnesia数据库文件,然后执行以下操作。
编写一个使用“坏”节点名称和Mnesia目录独立启动Mnesia的escript,从已知的良好节点复制表,然后关闭Mnesia。在坏节点上运行该escript。
复制表并正常关闭Mnesia的行为使节点恢复与群集同步。然后,当您在坏节点上启动应用程序时,它将加入并与群集保持同步。
当然,这种描述缺乏准确的细节,但这是它的要点。这种做法肯定不那么蛮力,但除非你有大量的数据要复制,否则我认为这种方式最快,最干净。