如何删除额外的节点

Posted

技术标签:

【中文标题】如何删除额外的节点【英文标题】:how do I remove an extra node 【发布时间】:2010-10-23 15:00:41 【问题描述】:

我有一组 erlang 节点,它们通过 Mnesia 的“extra_db_nodes”复制它们的数据......我需要升级硬件和软件,所以当我从一个节点到另一个节点时,我必须分离一些节点。

如何删除一个节点并仍然保留插入的数据?

[update] 删除节点与添加节点一样重要。随着时间的推移,随着集群的增长,它也必须收缩。如果没有,那么 Mnesia 将忙于尝试将数据发送到不存在的节点,从而填满队列并保持网络繁忙。

[最终更新] 在翻阅 erlang/mnesia 源代码后,我能够确定无法完全分离节点。虽然 del_table_copy 删除了表之间的链接,但它是不完整的。我会结束这个问题,但没有任何密切的描述是充分的。

【问题讨论】:

erlang 黑客有机会通过这里吗?低的。但是我发现这个问题很有趣,并且不看 erlang 和 mnesia,所以当我学会了它时,我可能会在一两年内回过头来回答一下!感谢您的有趣帖子 嗯,有 19 个记忆障碍问题,所以几率并不低。问题越小众,您可能需要等待更长的时间才能得到答案,仅此而已。 破解代码并寻找自己只是时间问题。下周我的休假结束时,我会有很多时间。 当你说你正在通过 Mnesia 的“extra_db_nodes”值复制数据时,这并不正确。 extra_db_nodes 只是告诉 mnesia 要连接哪些其他节点 - 除非您启动一个新的空数据库节点,否则不应使用它。在正常操作中(将模式复制到新节点之后),extra_db_nodes 是不必要的,因为模式还告诉 mnesia 连接到哪些节点。 【参考方案1】:

我希望我很久以前就发现了这个:http://weblambdazero.blogspot.com/2008/08/erlang-tips-and-tricks-mnesia.html

基本上,使用正常运行的集群......

登录要移除的集群

停止失忆

mnesia:stop().

登录到集群上的不同节点

删除架构

mnesia:del_table_copy(schema, node@host.domain).

【讨论】:

【参考方案2】:

我参加聚会非常迟到,但在寻找解决同一问题的方法时在文档中看到了此信息:

"函数调用 mnesia:del_table_copy(架构, mynode@host) 删除节点 来自 Mnesia 系统的“mynode@host”。 如果 mnesia 正在运行,则调用失败 'mynode@host'。其他 mnesia 节点 永远不会尝试连接到该节点 再次。注意,如果有光盘 节点上的常驻模式 'mynode@host',整个 mnesia 目录应该被删除。这个可以 使用 mnesia:delete_schema/1 完成。 如果 mnesia 在 节点“mynode@host”和目录 还没有被清除,mnesia的 行为未定义。” (http://www.erlang.org/doc/apps/mnesia/Mnesia_chap5.html#id74278)

我认为以下内容可能会满足您的要求:

AllTables = mnesia:system_info(tables),
DataTables = lists:filter(fun(Table) -> Table =/= schema end,
                          AllTables),

RemoveTableCopy = fun(Table,Node) ->
  Nodes = mnesia:table_info(Table,ram_copies) ++
          mnesia:table_info(Table,disc_copies) ++
          mnesia:table_info(Table,disc_only_copies),
  case lists:member(Node,Nodes) of
    true -> mnesia:del_table_copy(Table,Node);
    false -> ok
  end
end,

[RemoveTableCopy(Tbl,'gone@gone_host') || Tbl <- DataTables].

rpc:call('gone@gone_host',mnesia,stop,[]),
rpc:call('gone@gone_host',mnesia,delete_schema,[SchemaDir]),
RemoveTablecopy(schema,'gone@gone_host').

不过,我没有测试它,因为我的场景略有不同。

【讨论】:

【参考方案3】:

我当然使用过这种方法来执行此操作(支持 mnesia:del_table_copy/2 使用)。请参阅下面的 removeNode/1:

-module(tool_bootstrap).

-export([bootstrapNewNode/1, closedownNode/0,
     finalBootstrap/0, removeNode/1]).

-include_lib("records.hrl").

-include_lib("stdlib/include/qlc.hrl").

bootstrapNewNode(Node) ->
    %% Make the given node part of the family and start the cloud on it
    mnesia:change_config(extra_db_nodes, [Node]),
    %% Now make the other node set things up
    rpc:call(Node, tool_bootstrap, finalBootstrap, []).

removeNode(Node) ->
    rpc:call(Node, tool_bootstrap, closedownNode, []),
    mnesia:del_table_copy(schema, Node).

finalBootstrap() ->
    %% Code removed to actually copy over my tables etc...
    application:start(cloud).

closedownNode() ->
    application:stop(cloud), mnesia:stop().

【讨论】:

虽然这段代码看起来可以工作,但它并没有清理所有数据。 del_table_copy 不会从 extra_db_node 列表中删除节点。实际上,源代码中没有完全删除节点的代码。 是的,你是对的。为了清楚起见,我删除了所有特定于我的应用程序的代码... 啊——是的。我应该阅读原始问题。我的解决方案确实达到了我想要的效果——不再让我的(已删除)节点托管数据的复制副本。但我从未检查过更改后 extra_db_nodes 设置的内容...【参考方案4】:

如果您在要删除的节点以外的节点上复制了表(添加了表副本),那么您已经很好 - 只需删除节点即可。

如果您想稍微整洁一些,您可以通过 mnesia:del_table_copy/2 从您将要删除的节点中删除表副本。

通常,mnesia 优雅地处理节点丢失并检测节点重新加入(重新启动的节点从继续运行的节点获取新的表副本,未重新启动的节点被检测为网络分区事件)。 Mnesia 不会为已关闭的节点消耗 CPU 或网络流量。我认为,虽然我没有在源代码中确认,但 mnesia 不会重新连接到自动关闭的节点 - 关闭的节点预计会重新启动 (mnesia) 并重新连接。

mnesia:add_table_copy/3mnesia:move_table_copy/3mnesia:del_table_copy/2 是您应该查看的用于实时模式管理的函数。

extra_db_nodes 参数仅应在初始化新的 DB 节点时使用 - 一旦新节点具有架构副本,它就不需要 extra_db_nodes 参数。

【讨论】:

我对这个答案持怀疑态度。我喜欢一般信息,但是,它不是最新的。您提到的三种方法未包含在 R13B 版本中。对 R13A 代码的搜索没有发现任何类似的方法。 继续搜索源代码,我发现一些迹象表明添加额外节点时使用了对 mnesia_controller:add_list/2 的调用。有一条评论建议调用 mnesia_recover:disconnect_nodes/1,但是,该方法在任何地方都不存在,可能只是一个错字; mnesia_recover:disconnect/1 存在。 我说的是 delete_table_copy 而不是 del_table 副本,但除此之外,这些方法是存在的、记录在案的和最新的。您不必手动断开节点 - mnesia 会自行处理节点断开连接。只需关闭不需要的节点。或者使用 net_kernel:disconnect/1 强制执行。 del_table_copy 不会从 extra_db_nodes 列表中删除节点。 当然可以,但是为什么它们首先出现在 extra_db_nodes 列表中?加入集群时您只需要 extra_db_nodes - 之后它比其他任何事情都更具障碍。您可以 change_config 在运行时更改 extra_db_nodes,但为什么要这样做?你不应该在正常操作中指定extra_db_nodes,所以你的问题不是删除节点时如何从extra_db_nodes中删除东西,而是在新节点加入集群后如何避免在任何时候使用extra_db_nodes。

以上是关于如何删除额外的节点的主要内容,如果未能解决你的问题,请参考以下文章

如何触发JQuery treeview的渲染

如何删除 imageView 上方和下方的额外空间?

额外的滚动条如何删除?

如何从加载的商店 sencha touch 中删除额外参数

如何从谷歌地图中删除额外信息

如何删除这些讨厌的额外空间