rabbitmq——集群启动问题

本文分析了mnesia集群在全部节点停止后再启动时遇到的数据同步问题。详细解释了问题产生的原因,涉及到mnesia_controller.erl中的初始加载逻辑。探讨了不同超时设置下程序的行为差异,以及ejabberd和rabbitmq的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题现象:

mnesia集群中的节点全部停止,然后再次启动,偶然出现所有节点都在一直等待数据同步的现象。

问题原因:

翻看相关源码后发现问题:

mnesia_contorller.erl
%% 选择可以进行数据加载的 table
initial_safe_loads() ->
    case val({schema, storage_type}) of
        ram_copies ->
            %% 如果表为仅在内存中存储, 可以直接加载
            %% 因此停止前记录的 down 掉的节点设置为 []
            Downs = [],
            Tabs = val({schema, local_tables}) -- [schema],
            LastC = fun(T) -> last_consistent_replica(T, Downs) end,
            lists:zf(LastC, Tabs);
        disc_copies ->
            %% 如果表为 磁盘存储, 需要判断停止前集群节点的存活状态
            Downs = mnesia_recover:get_mnesia_downs(),
            Tabs = val({schema, local_tables}) -- [schema],
            LastC = fun(T) -> last_consistent_replica(T, Downs) end,
            lists:zf(LastC, Tabs)
    end.

last_consistent_replica(Tab, Downs) ->
    %% 查找表结构信息
    Cs = val({Tab, cstruct}),
    %% 查找该表所有复制的节点信息
    Copies = mnesia_lib:copy_holders(Cs),
    ...
    %% 查找可以用来复制的远端节点
    %% 注意 是远端节点 表示除去了节点本身
    %% 另外 集群中先于本节点停止的节点需排除
    BetterCopies0 = mnesia_lib:remote_copy_holders(Cs) -- Downs,
    ...
    if
        %% 该表仅在本节点进行拷贝复制
        Copies == [node()] ->
            {true, {Tab, local_only}};
        ...
        %% 不是集群中最后一个停止的节点
        %% 为防止可能的数据不一致 需从远端记载数据
        BetterCopies /= [], Masters /= [node()] ->
            false;
        %% 
        true ->
            {true, {Tab, initial}}
    end.

这么一来,不是集群中最后一个停止的节点先启动时,对于disc存储类型的表,都不会进行加载。并且在mneia_gvar会记录{{Tab, where_to_read}, nowhere}。

调用mnesia:wait_for_tables(Tabs, Timeout)后最终会在mnesia_gvar中查找{Tab, where_to_read}对应的值。

如果对应的Table未加载,即为nowhere,并且Timeout设置为infinity,那么程序就会出现死等。

如果Timeout设置为具体的值,那么超时仍未完成加载的话,需要业务根据实际需求进行特殊处理。通常是抛出异常让程序无法正常启动。

注:ejabberd采用的死等的方式,rabbitmq则是采用超时抛出异常停止运行。

转载于:https://my.oschina.net/hncscwc/blog/367584

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值