rabbitmq——集羣啓動問題

問題現象: java

mnesia集羣中的節點所有中止,而後再次啓動,偶然出現全部節點都在一直等待數據同步的現象。 node

問題緣由: code

翻看相關源碼後發現問題: rabbitmq

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}對應的值。 rem

若是對應的Table未加載,即爲nowhere,而且Timeout設置爲infinity,那麼程序就會出現死等。 get

若是Timeout設置爲具體的值,那麼超時仍未完成加載的話,須要業務根據實際需求進行特殊處理。一般是拋出異常讓程序沒法正常啓動。 同步

注:ejabberd採用的死等的方式,rabbitmq則是採用超時拋出異常中止運行。 源碼

相關文章
相關標籤/搜索