1. 程式人生 > >[ES]elasticsearch章4 ES的META們

[ES]elasticsearch章4 ES的META們

在介紹Meta更新流程前,我們先介紹一下ES中Meta的組成、儲存方式和恢復方式。

1. Meta:ClusterState、MetaData、IndexMetaData

Meta是用來描述資料的資料。在ES中,Index的mapping結構、配置、持久化狀態等就屬於meta資料,叢集的一些配置資訊也屬於meta。這類meta資料非常重要,假如記錄某個index的meta資料丟失了,那麼叢集就認為這個index不再存在了。ES中的meta資料只能由master進行更新,master相當於是叢集的大腦。

ClusterState

叢集中的每個節點都會在記憶體中維護一個當前的ClusterState,表示當前叢集的各種狀態。ClusterState中包含一個MetaData的結構,MetaData中儲存的內容更符合meta的特徵,而且需要持久化的資訊都在MetaData中,此外的一些變數可以認為是一些臨時狀態,是叢集執行中動態構建出來的。

ClusterState內容包括:
    long version: 當前版本號,每次更新加1
    String stateUUID:該state對應的唯一id
    RoutingTable routingTable:所有index的路由表
    DiscoveryNodes nodes:當前叢集節點
    MetaData metaData:叢集的meta資料
    ClusterBlocks blocks:用於遮蔽某些操作
    ImmutableOpenMap<String, Custom> customs: 自定義配置
    ClusterName clusterName:叢集名

MetaData

上面提到,MetaData更符合meta的特徵,而且需要持久化,那麼我們看下這個MetaData中主要包含哪些東西:

MetaData中需要持久化的包括:
    String clusterUUID:叢集的唯一id。
    long version:當前版本號,每次更新加1
    Settings persistentSettings:持久化的叢集設定
    ImmutableOpenMap<String, IndexMetaData> indices: 所有Index的Meta
    ImmutableOpenMap<String, IndexTemplateMetaData> templates:所有模版的Meta
    ImmutableOpenMap<String, Custom> customs: 自定義配置

我們看到,MetaData主要是叢集的一些配置,叢集所有Index的Meta,所有Template的Meta。下面我們再分析一下IndexMetaData,後面還會講到,雖然IndexMetaData也是MetaData的一部分,但是儲存上卻是分開儲存的。

IndexMetaData

IndexMetaData指具體某個Index的Meta,比如這個Index的shard數,replica數,mappings等。

IndexMetaData中需要持久化的包括:
    long version:當前版本號,每次更新加1。
    int routingNumShards: 用於routing的shard數, 只能是該Index的numberOfShards的倍數,用於split。
    State state: Index的狀態, 是個enum,值是OPEN或CLOSE。
    Settings settings:numbersOfShards,numbersOfRepilicas等配置。
    ImmutableOpenMap<String, MappingMetaData> mappings:Index的mapping
    ImmutableOpenMap<String, Custom> customs:自定義配置。
    ImmutableOpenMap<String, AliasMetaData> aliases: 別名
    long[] primaryTerms:primaryTerm在每次Shard切換Primary時加1,用於保序。 ImmutableOpenIntMap<Set<String>> inSyncAllocationIds:處於InSync狀態的AllocationId,用於保證資料一致性,下一篇文章會介紹。

2. Meta的儲存

首先,在啟動ES的一個節點時,會配置一個data目錄,例如下面這個目錄。該節點只有一個單shard的Index。

$tree
.
`-- nodes
    `-- 0
        |-- _state
        |   |-- global-1.st
        |   `-- node-0.st |-- indices | `-- 2Scrm6nuQOOxUN2ewtrNJw | |-- 0 | | |-- _state | | | `-- state-0.st | | |-- index | | | |-- segments_1 | | | `-- write.lock | | `-- translog | | |-- translog-1.tlog | | `-- translog.ckp | `-- _state | `-- state-2.st `-- node.lock

我們看到,ES程序會把Meta和Data都寫入這個目錄中,其中目錄名為_state的代表該目錄儲存的是meta檔案,根據檔案層級的不同,共有3種meta的儲存:

  • nodes/0/_state/:

這層目錄在節點級別,該目錄下的global-1.st檔案儲存的是上文介紹的MetaData中除去IndexMetaData的部分,即一些叢集級別的配置和templates。node-0.st中儲存的是NodeId。

  • nodes/0/indices/2Scrm6nuQOOxUN2ewtrNJw/_state/:

這層目錄在index級別,2Scrm6nuQOOxUN2ewtrNJw是IndexId,該目錄下的state-2.st檔案儲存的是上文介紹的IndexMetaData。

  • nodes/0/indices/2Scrm6nuQOOxUN2ewtrNJw/0/_state/:

這層目錄在shard級別,該目錄下的state-0.st儲存的是ShardStateMetaData,包含是否是primary和allocationId等資訊。ShardStateMetaData是在IndexShard模組中管理,與其他Meta關聯不大,本文不做過多介紹。

可以看到,叢集相關的MetaData和Index的MetaData是在不同的目錄中儲存的。另外,叢集相關的Meta會在所有的MasterNode和DataNode上儲存,而Index的Meta會在所有的MasterNode和儲存了該Index資料的DataNode上儲存。

這裡有個問題是,MetaData是由Master管理的,為什麼DataNode上也要儲存MetaData呢?主要原因是考慮到資料的安全性,很多使用者沒有考慮Master節點的高可用和資料高可靠,在部署ES叢集時只配置了一個MasterNode,如果這個節點不可用,就會出現Meta丟失,後果非常嚴重。

3. Meta的恢復

假設ES叢集重啟了,那麼所有程序都沒有了之前的Meta資訊,需要有一個角色來恢復Meta,這個角色就是Master。所以ES叢集需要先進行Master選舉,選出Master後,才會進行故障恢復。

當Master選舉出來後,Master程序還會等待一些條件,比如叢集當前的節點數大於某個數目等,這是避免有些DataNode還沒有連上來,造成不必要的資料恢復等。

當Master程序決定進行恢復Meta時,它會向叢集中的MasterNode和DataNode請求其機器上的MetaData。對於叢集的Meta,選擇其中version最大的版本。對於每個Index的Meta,也選擇其中最大的版本。然後將叢集的Meta和每個Index的Meta再組合起來,構成當前的最新Meta。