如何删除额外的节点
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/3
、mnesia:move_table_copy/3
和 mnesia: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。以上是关于如何删除额外的节点的主要内容,如果未能解决你的问题,请参考以下文章