是否可以从mnesia集群中的网络分区恢复而无需重新启动任何涉及的节点?如果是这样,那怎么办呢?
我特别感兴趣的是:
如何使用标准OTP mnesia(v4.4.7)
什么自定义代码,如果任何人需要编写以实现这一点(例如订阅mnesia running_paritioned_network事件,确定新的master,从非master到master合并记录,从新master强制加载表,清除运行的parititioned网络事件 - 将非常感谢示例代码.
或者,mnesia明确地不支持在线恢复,并且要求重新启动属于非主分区的节点.
虽然我很欣赏一般分布式系统理论的指针,但在这个问题上,我只对erlang/OTP mnesia感兴趣.
经过一些实验,我发现了以下内容:
如果两个节点之间存在节点断开连接并且没有重新启动mnesia,则Mnesia认为要对网络进行分区.
即使在断开连接期间没有发生Mnesia读/写操作,也是如此.
必须重新启动Mnesia本身才能清除分区网络事件 - force_load_table
在网络分区后无法重新启动.
只有Mnesia需要重新启动才能清除网络分区事件.您无需重新启动整个节点.
Mnesia通过让新重新启动的Mnesia节点使用来自另一个Mnesia节点(启动表加载算法)的数据覆盖其表数据来解析网络分区.
通常,节点将从最长的节点复制表(这是我看到的行为,我没有验证这是明确编码的,而不是其他东西的副作用).如果断开节点与群集的连接,请在两个分区(断开连接的节点及其旧对等体)中进行写入,关闭所有节点并重新启动所有节点,然后再次启动断开连接的节点,断开连接的节点将被视为主节点及其数据将覆盖所有其他节点.没有表比较/校验和/仲裁行为.
因此,为了回答我的问题,可以通过mnesia:stop(), mnesia:start()
在您决定丢弃其数据的分区中的节点上执行来执行半在线恢复(我将其称为丢失分区).执行mnesia:start()
调用将使节点联系分区另一侧的节点.如果丢失分区中有多个节点,您可能希望将表加载的主节点设置为获胜分区中的节点 - 否则我认为它有可能从丢失分区中的另一个节点加载表,从而返回分区网络状态.
遗憾的是,mnesia不支持在启动表加载阶段合并/协调表内容,也不提供在启动后返回表加载阶段.
合并阶段特别适合于ejabberd,因为节点仍然具有用户连接,因此知道它拥有/应该是哪个用户记录是最新的(假设每个群集有一个用户连接).如果存在合并阶段,则节点可以过滤用户数据表,保存连接用户的所有记录,按常规加载表,然后将保存的记录写回mnesia集群.