- 版本: ElasticSearch 5.4.4
- Lucene版本: 6.5.1
- java: open jdk 1.8
DIscovery模塊的功能
Discover模塊主要是負責發現集羣中的節點,以及選擇主節點。兼容多種Discovery類型,包含亞馬遜的ec2,谷歌的GCE等 本文內置的爲zenDiscovery。
位置:
Interface:org.elasticsearch.discovery #這時接口類
Discription:
A pluggable module allowing to implement discovery of other nodes, publishing of the cluster
state to all nodes, electing a master of the cluster that raises cluster state change events.
class: org.elasticsearch.discovery.zen #實現類
主要是爲了進行主節點選取:封裝了節點發現、選主等流程
class: org.elasticsearch.discovery.zen.ElectMasterService 具體的選主實現
主從模式的ES
考慮到ES的實際應用情況:
- 中等集羣,通常剛沒有那麼多節點(上千個)。
- 單節點維護的連接數通常少於節點數量
- 網絡環境比較問題,節點加入和離開不是很頻繁。
因此考慮上千甚至是數錢節點的加入是沒必要的,因爲沒有采用分佈式哈希表(DHT)而採用的是主從模式。
ES的選主算法
ES主要採用的Bully算法,本質上就是選取id最大或者最小的作爲主節點。當然爲了維持一致性我們還有考慮很多額外的細節問題。這裏首先我們研究一下ElectMasterService類
成員變量
private volatile int minimumMasterNodes;
// 觸發選主所需要的最小節點數量。 必須爲半數以上
成員類
public static class MasterCandidate {
public static final long UNRECOVERED_CLUSTER_VERSION = -1;
final DiscoveryNode node;
final long clusterStateVersion;
/*此處省略*/
/**
* compares two candidates to indicate which the a better master.
* A higher cluster state version is better
*
* @return -1 if c1 is a batter candidate, 1 if c2.
*/
public static int compare(MasterCandidate c1, MasterCandidate c2) {
// we explicitly swap c1 and c2 here. the code expects "better" is lower in a sorted
// list, so if c2 has a higher cluster state version, it needs to come first.
int ret = Long.compare(c2.clusterStateVersion, c1.clusterStateVersion);
if (ret == 0) {
ret = compareNodes(c1.getNode(), c2.getNode());
}
return ret;
}
}
這裏比較兩個候選節點主要是根據每個節點的clusterStateVersion , clusterStateVersion越大,優先級越高。clusterStateVersion相同時,進入compareNodes,其內部按照節點的Id比較(Id爲節點第一次啓動時隨機生成)取比較小的。當clusterStateVersion越大,優先級越高。這是爲了保證新Master擁有最新的clusterState(即集羣的meta),避免已經commit的meta變更丟失。因爲Master當選後,就會以這個版本的clusterState爲基礎進行更新。
整個流程如下;
- 觸發選主: 參與選主流程的必須要有一半以上。
- 決定master: 選出臨時master後, 加入其中的節點必須達到法定人數。
- gateway選舉元信息:向有master選舉資格的節點發送請求獲取元數據,反饋必須達到法定數量。
- master發佈成功數量爲多數。
選取臨時節點:findMaster
org.elasticsearch.discovery.zen.ZenDiscover.findMaster
首先節點會通過ping所有的節點然後獲取節點的列表fullPingResponse,當然肯定不會包括本節點,但是會單獨添加到本節點到fullPingResponse
List<ZenPing.PingResponse> fullPingResponses = pingAndWait(pingTimeout).toList();
然後es會構建兩個列表;activeMasters和masterCandidates
activeMaster: 將每個節點認爲的當前master添加到列表中(除去本身)。正常情況下有一個節點,但是異常情況下也可能存在多個。
masteCandinates: 列表master候選者的列表,遍歷列表確定不具備master資格的節點。
這時如果activeMaster爲空則從masterCandinate選取新的節點 (詳情見electMaterService類實現)