Elasticsearch 節點選舉和primary分片

xz43發表於2019-12-04

前提概要

預設情況下,elasticsearch叢集中每個節點都有成為master主節點的資格,也都可以儲存資料,還可以對外提供查詢服務。這些功能是由兩個屬性控制的— node.masternode.data。預設情況下這兩個屬性的值都是true。下面詳細介紹一下這兩個屬性的含義以及不同組合可以達到的效果。

node.master 這個屬性表示節點是否具有成為主節點的資格

注意:此屬性的值為true,並不意味著這個節點就是主節點。因為真正的主節點,是由多個具有主節點資格的節點進行選舉產生的。所以,這個屬性只是代表這個節點是不是具有主節點選舉資格。 下面會討論如何被選舉成為真正的主節點。

node.data 這個屬性表示節點是否用來儲存資料。

而這兩個屬性可以有以下四種組合:

1)      node.master: true  node.data: true

這種組合表示這個節點即有成為主節點的資格,又可以儲存資料。這個時候如果某個節點被選舉成為了真正的主節點,那麼他還要儲存資料,這樣對於這個節點的壓力就比較大。elasticsearch預設每個節點都是這樣的配置,在測試環境下這樣做沒問題。實際生產環境下建議不要這樣設定,這樣相當於主節點和資料節點的角色混合到一塊了。

2)      node.master: false  node.data: true

這種組合表示這個節點沒有成為主節點的資格,也就不能參與選舉,只會儲存資料。這個節點我們稱為data(資料)節點。在叢集中需要單獨設定幾個這樣的節點負責儲存資料,後期提供儲存和查詢服務。

3)      node.master: true  node.data: false

這種組合表示這個節點不會儲存資料,有成為主節點的資格,可以參與選舉,有可能成為真正的主節點。這個節點我們稱為master節點。

4)       node.master: false  node.data: false

這種組合表示這個節點即不會成為主節點,也不會儲存資料,這個節點的意義是作為一個client(客戶端)節點,主要是針對海量請求的時候可以進行負載均衡。

預設情況下,每個節點都有成為主節點的資格,也會儲存資料,還會處理客戶端的請求。在一個生產叢集中我們可以對這些節點的職責進行劃分。

Master 選舉

Master 主節點作為cluster的靈魂必須要有,還必須要唯一,否則叢集就出大問題了,關於分散式系統的master ,最有名的當然要數paxos演算法,在它的基礎上出現了非常多的變體演算法。但是paxos的功能遠遠超出了master選舉,一致性才是它的目標,任何需要實現一致性的問題都可以使用該演算法。叢集有一個問題就是brain split:一個叢集因為網路問題導致多個master主節點選舉出來而分裂。這也是master選舉必須要解決的問題。

具體原理如下(下面的master節點即為主節點):

1)      對所有可以成為master的節點根據 nodeId排序,每次選舉每個節點都把自己所知道節點排一次序,然後選出第一個(第0位)節點,暫且認為它是master節點;

2)      如果對某個節點的投票數達到一定的值(可以成為master節點數n/2+1)並且該節點自己也選舉自己,那這個節點就是master。否則重新選舉;

3)      對於brain split問題,需要把候選master節點最小值設定為可以成為master節點數n/2+1;

以上就是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的方法。可以看到,它的做法就是對候選節點排序然後直接將第一個返回。當然這只是上面所說的第一條。如果每個節點都只是選舉自己排序後的節點的第一個肯定會導致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排序。

為了解決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官網)來說明:

Elasticsearch 節點選舉和primary分片

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

Shard 機制

單臺機器無法儲存大量資料,elasticsearch可以將一個索引中的資料切分為多個shard(一個index包含多個shard ),分佈在多臺伺服器上儲存。有了shard就可以橫向擴充套件,儲存更多資料,讓搜尋和分析等操作分佈到多臺伺服器上去執行,提升吞吐量和效能。每個shard都是一個lucene index。

Elasticsearch 節點選舉和primary分片

shard 分為兩類:

primary shard 主分片,承擔 讀寫請求負載;

replica shard 副本分片,是主分片的副本,負責容錯,以及承擔 請求負載;

任何一臺伺服器隨時可能故障或當機,此時shard可能就會丟失,因此可以為每個shard建立多個replica副本。replica可以在shard故障時提供備用服務,保證資料不丟失,多個replica還可以提升搜尋操作的吞吐量和效能。

Shard 主要特性:

1)      index 包含多個shard;

2)      每個shard都是一個最小工作單元,承載部分資料,lucene例項,完整的建立索引和處理請求的能力;

3)      增減節點時,shard會自動在nodes中負載均衡;

4)      primary shard 和replica shard,每個document肯定只存在於某一個primary shard以及其對應的replica shard中,不可能存在於多個primary shard;

5)      replica shard 是primary shard的副本,負責容錯,以及承擔讀請求負載;

6)      primary shard 的數量在建立索引的時候就固定了,replica shard的數量可以隨時修改;

7)      primary shard 的預設數量是5,replica預設是1,預設有10個shard,5個primary shard,5個replica shard;

8)      primary shard 不能和自己的replica shard放在同一個節點上 (否則節點當機,primary shard和副本都丟失,起不到容錯的作用),但是可以和其他primary shard的replica shard放在同一個節點上;

primary shard 當機後,新master將某個replica shard提升為primary shard。重啟當機node,master copy replica到該node,使用原有的shard並同步當機後的修改。原有的primary shard降級為replica shard

假設有3個節點,9個shard (3個primary shard,每個 primary shard 有 2 個 replica shard),具體分配如下表,假設 Node1 為 master

Node1

Node2

Node3

P0 , P1-1 , P2-1

P1 , P0-1 , P2-2

P2 , P1-2 , P0-2

如果 Node1 當機,此時叢集狀態為 red, 叢集會自動選舉一個節點為新的 master 主節點(假設為 Node2)。

新的 master Node2 將 P0-1 這個 replica shard 升級成 primary shard, 此時 叢集狀態為 yellow。

重新啟動 Node1 節點, 會自動更新資料,此時叢集狀態為 green。

 

建議

叢集中設定3臺以上的節點作為master節點【node.master: true  node.data: false】。這些節點只負責成為主節點,維護整個叢集的狀態。

再根據資料量設定一批data節點【node.master: false  node.data: true】。這些節點只負責儲存資料。

後期提供建立索引和查詢索引的服務,如果使用者請求比較頻繁,這些節點的壓力也會比較大。所以在叢集中建議再設定一批client節點【node.master: false  node.data: false】。這些節點只負責處理使用者請求,實現請求轉發,負載均衡等功能。

配置要求

master 節點:普通伺服器即可(CPU、記憶體 消耗一般);

data 節點:主要消耗磁碟,記憶體;

client 節點:普通伺服器即可(如果要進行分組聚合操作的話,建議這個節點記憶體也分配多一點)。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-2666851/,如需轉載,請註明出處,否則將追究法律責任。

相關文章