在线mnesia从网络分区恢复

时间:2009-03-08 23:40:34

标签: erlang mnesia

是否可以从mnesia群集中的网络分区恢复而无需重新启动任何涉及的节点?如果是这样,那怎么办呢?

我特别感兴趣的是:

  • 如何使用标准OTP mnesia(v4.4.7)
  • 完成此操作
  • 如果需要编写任何自定义代码以实现此目的(例如订阅mnesia running_paritioned_network事件,确定新的master,将记录从非master合并到master,从新master强制加载表,清除运行的parititioned network事件 - 非常感谢示例代码。
  • 或者,mnesia明确地不支持在线恢复,并且要求重新启动属于非主分区的节点。

虽然我很欣赏一般分布式系统理论的指针,但在这个问题上,我只对erlang / OTP mnesia感兴趣。

3 个答案:

答案 0 :(得分:15)

经过一些实验,我发现了以下内容:

  • 如果两个节点之间存在节点断开连接并且重新连接没有重新启动mnesia,则Mnesia认为要对网络进行分区。
  • 即使在断开连接期间没有发生Mnesia读/写操作,也是如此。
  • 必须重新启动Mnesia才能清除分区网络事件 - 在网络分区后,您无法force_load_table
  • 只需重新启动Mnesia即可清除网络分区事件。您无需重新启动整个节点。
  • Mnesia通过让新重新启动的Mnesia节点使用来自另一个Mnesia节点(启动表加载算法)的数据覆盖其表数据来解析网络分区。
  • 一般来说,节点会从最长的节点复制表格(这是我看到的行为,我没有证实这是明确编码的,而不是其他东西的副作用)。如果断开节点与群集的连接,请在两个分区(断开连接的节点及其旧对等体)中进行写入,关闭所有节点并重新启动它们,然后再次启动断开连接的节点,断开连接的节点将被视为主节点及其数据将覆盖所有其他节点。没有表格比较/校验和/仲裁行为。

因此,为了回答我的问题,可以通过在您决定丢弃其数据的分区中的节点上执行mnesia:stop(), mnesia:start()来执行半在线恢复(我将其称为丢失分区)。执行mnesia:start()调用将导致节点联系分区另一侧的节点。如果丢失分区中有多个节点,您可能希望将表加载的主节点设置为获胜分区中的节点 - 否则我认为它有可能从丢失分区中的另一个节点加载表,从而返回分区网络状态。

不幸的是,mnesia不支持在启动表加载阶段合并/协调表内容,也不提供在启动后返回表加载阶段。

合并阶段特别适合ejabberd,因为节点仍然具有用户连接,因此知道它拥有/应该是最新的用户记录(假设每个群集有一个用户连接)。如果存在合并阶段,则节点可以过滤用户数据表,保存连接用户的所有记录,按常规加载表,然后将保存的记录写回mnesia集群。

答案 1 :(得分:0)

它的工作原理如下。想象一下充满了鸟儿的天空。拍照,直到你得到所有的鸟。 将图片放在桌子上。将图片映射到彼此上。所以你一次看到每只鸟。你是每只鸟吗?好。那时你就知道了。系统稳定。 记录所有鸟类的声音(消息)并拍摄更多照片。然后重复一遍。

如果您有节点拆分。返回最新的常见稳定快照。并尝试**重播之后附加的内容。 :)

更好地描述了 “分布式快照:确定分布式系统的全局状态” K. MANI CHANDY和LESLIE LAMPORT

**我认为在尝试重播发生的事情时,确定谁的时钟是有问题的

答案 2 :(得分:0)

Sara的答案很棒,甚至可以查看关于CAP的文章。 Mnesia开发人员为CA牺牲了P.如果你需要P,那么你应该选择你想要牺牲的CAP,而不是选择另一个存储。例如CouchDB(牺牲C)或Scalaris(牺牲A)。