elasticsearch的master選舉機制


master作為cluster的靈魂必須要有,還必須要唯一,否則集群就出大問題了。因此master選舉在cluster分析中尤為重要。對於這個問題我將分兩篇來分析。第一篇也就是本篇,首先會簡單說一說mater選舉的一些算法,及elasticsearch的選舉原理。第二篇也就是下一篇,會結合zenDiscovery代碼為仔細分析elasticsearch的master選舉的實現。

簡單來說master的作用跟單個jvm中的同步關鍵字synchronized相同,集群中多節點協調工作必須要保證數據的一致性,但是不同節點分布在不同的jvm中,不可能用jvm的同步機制。所以需要一個“鎖”,節點操作集群中的資源時都通過它來解決一致性問題,這就是master。關於分布式系統的master選舉算法有很多,最有名的當然要數paxos算法,在它的基礎上出現了非常多的變體算法。關於這個算法請參考相關網頁和資料,不是一兩句話能說清楚的,這里不再祥述。但是paxos的功能遠遠超出了master選舉,一致性向才是它的目標,任何需要實現一致性的問題都可以使用該算法,因此zookeeper功能遠遠不止master選舉。還有一種比較簡單的算法就是Bully,它通過一定的直接給每個節點賦予一唯一的ID,這些ID是可以排序的,每次master選舉都會選舉ID最大的節點。這種實現非常簡單。但是會存在一些問題,在master負載過重時它會假死,於是第二大節點就成為了master節點。因此假死master節點因負載減輕又活了過來,於是他又被選為master,然后又假死……,這種情況可能一直存在導致系統不穩定。

集群還有一個問題就是brain split:一個集群因為網絡問題導致多個master選舉出來而分裂。這也是master選舉必須要解決的問題。elasticsearch的master選舉原理我覺得是在bully的基礎上做了改進。相比於paxos實現的zookeeper它完美的解決了master選舉問題,但不如zookeeper強大,因為zookeeper功能遠遠超出了master選舉,它的master選舉卻不需要這么多功能。它原理如下:

  1. 對所有可以成為master的節點根據nodeId排序,每次選舉每個節點都把自己所知道節點排一次序,然后選出第一個(第0位)節點,暫且認為它是master節點。
  2. 如果對某個節點的投票數達到一定的值(可以成為master節點數n/2+1)並且該節點自己也選舉自己,那這個節點就是master。否則重新選舉。
  3. 對於brain split問題,需要把候選master節點最小值設置為可以成為master節點數n/2+1(quorum )

以上就是master選舉的三條原則,其實第三天包含在第二條之中,為了說明brain split問題這里單獨拿出來說一下。下面看一下ElectMasterService的相關代碼,來補充說明一下一上的文字描述:

 public DiscoveryNode electMaster(Iterable<DiscoveryNode> nodes) {
        List<DiscoveryNode> sortedNodes = sortedMasterNodes(nodes);
        if (sortedNodes == null || sortedNodes.isEmpty()) {
            return null;
        }
        return sortedNodes.get(0);
    }

上面就是選舉master的方法,可以看到,它的做法就是對候選節點排序然后直接將第一個返回。當然這只是上面所說的第一條。其實只有這個是不能夠保證maser選舉順利的,之前也看到一些文章分析elasticsearch的master選舉,只提到了這個點和這一部分代碼,應該是作者沒有仔細研究Discovery代碼而導致的疏忽。如果每個節點都只是選舉自己排序后的節點的第一個肯定會導致brain split和選舉不一致。master比較的方法也比較簡單如下所示:

private static class NodeComparator implements Comparator<DiscoveryNode> {

        @Override
        public int compare(DiscoveryNode o1, DiscoveryNode o2) {
            if (o1.masterNode() && !o2.masterNode()) {
                return -1;
            }
            if (!o1.masterNode() && o2.masterNode()) {
                return 1;
            }
            return o1.id().compareTo(o2.id());
        }
    }

以上是節點排序比較器,可以看到它只是比較了nodeId,因此是按nodeId排序。從這兩兩段代碼來看很像是bully算法的實現。為了解決brain split問題開發者加入了master候選數據量限制,代碼如下:

   public boolean hasEnoughMasterNodes(Iterable<DiscoveryNode> nodes) {
        if (minimumMasterNodes < 1) {
            return true;
        }
        int count = 0;
        for (DiscoveryNode node : nodes) {
            if (node.masterNode()) {
                count++;
            }
        }
        return count >= minimumMasterNodes;
    }

通過比較節點能“看到”的候選master數量和配置的最小值來確定是否可以進行選舉,如果數量不夠會導致選舉不能進行,這樣就可以保證集群不會被分裂。下面以一個圖(圖片來自於elasticsearch官網)來說明:

假設之前選舉了A節點為master,兩個switch之間突然斷線了,這樣就分詞了兩部分。CDE和AB,因為 minimumMasterNodes的數目為3(集群中5個節點都可以成為master,3=5/2+1),因此cde會可以進行選舉假設C成為master。AB兩個節點因為少於3所以無法選舉,只能一直尋求加入集群,要么線路連通加入到CDE中要么就一直處於尋找集群狀態,這樣就保證了集群不分裂。

總結一下,本篇介紹了master選舉的兩種算法和elasticsearch的選舉原理,並分析了它原理中的兩條,第二條將在下一篇discovery中接下分析。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM