亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Elasticsearch分布式一致性原理剖析(二)-Meta篇

CntChen / 2290人閱讀

摘要:前言分布式一致性原理剖析系列將會對的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式原理以及其存在的問題等基于版本。中需要持久化的包括當(dāng)前版本號,每次更新加。收集不到足夠的,于是本次發(fā)布失敗,同時退出狀態(tài)。

前言
“Elasticsearch分布式一致性原理剖析”系列將會對Elasticsearch的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式、原理以及其存在的問題等(基于6.2版本)。前一篇的內(nèi)容包括了ES的集群組成、節(jié)點(diǎn)發(fā)現(xiàn)與Master選舉、錯誤檢測與集群擴(kuò)縮容等。本篇將在前一篇的基礎(chǔ)上,重點(diǎn)分析ES中meta更新的一致性問題,為了便于讀者理解 ,本文還介紹了Master管理集群的方式、meta組成、存儲方式等等。目錄如下:

Master如何管理集群

Meta組成、存儲和恢復(fù)

ClusterState的更新流程

如何解決當(dāng)前的一致性問題

小結(jié)

Master如何管理集群

在上一篇文章中,我們介紹了ES集群的組成,如何發(fā)現(xiàn)節(jié)點(diǎn),選舉Master等。那么在選舉出Master之后,Master如何管理集群呢?比如以下問題:

Master如何處理新建或刪除Index?

Master如何對Shard進(jìn)行重新調(diào)度,實(shí)現(xiàn)負(fù)載均衡?

既然要管理集群,那么Master節(jié)點(diǎn)必然需要以某種方式通知其他節(jié)點(diǎn),從而讓其他節(jié)點(diǎn)執(zhí)行相應(yīng)的動作,來完成某些事情。比如建立一個新的Index就需要將其Shard分配在某些節(jié)點(diǎn)上,在這些節(jié)點(diǎn)上需要創(chuàng)建出對應(yīng)Shard的目錄,并在內(nèi)存中創(chuàng)建對應(yīng)Shard的一些結(jié)構(gòu)等。

在ES中,Master節(jié)點(diǎn)是通過發(fā)布ClusterState來通知其他節(jié)點(diǎn)的。Master會將新的ClusterState發(fā)布給其他的所有節(jié)點(diǎn),當(dāng)節(jié)點(diǎn)收到新的ClusterState后,會把新的ClusterState發(fā)給相關(guān)的各個模塊,各個模塊根據(jù)新的ClusterState判斷是否要做什么事情,比如創(chuàng)建Shard等。即這是一種通過Meta數(shù)據(jù)來驅(qū)動各個模塊工作的方式。

在Master進(jìn)行Meta變更并通知所有節(jié)點(diǎn)的過程中,需要考慮Meta變更的一致性問題,假如這個過程中Master掛掉了,那么可能只有部分節(jié)點(diǎn)按照新的Meta執(zhí)行了操作。當(dāng)選舉出新的Master后,需要保證所有節(jié)點(diǎn)都要按照最新的Meta執(zhí)行操作,不能回退,因?yàn)橐呀?jīng)有節(jié)點(diǎn)按照新的Meta執(zhí)行操作了,再回退就會導(dǎo)致不一致。

ES中只要新Meta在一個節(jié)點(diǎn)上被commit,那么就會開始執(zhí)行相應(yīng)的操作。因此我們要保證一旦新Meta在某個節(jié)點(diǎn)上被commit,此后無論誰是master,都要基于這個commit來產(chǎn)生更新的meta,否則就可能產(chǎn)生不一致。本文會分析ES處理這一問題的策略和存在的問題。

Meta的組成、存儲和恢復(fù)

在介紹Meta更新流程前,我們先介紹一下ES中Meta的組成、存儲方式和恢復(fù)方式,不關(guān)心這部分內(nèi)容的讀者可以略過本節(jié)。

1. Meta:ClusterState、MetaData、IndexMetaData

Meta是用來描述數(shù)據(jù)的數(shù)據(jù)。在ES中,Index的mapping結(jié)構(gòu)、配置、持久化狀態(tài)等就屬于meta數(shù)據(jù),集群的一些配置信息也屬于meta。這類meta數(shù)據(jù)非常重要,假如記錄某個index的meta數(shù)據(jù)丟失了,那么集群就認(rèn)為這個index不再存在了。ES中的meta數(shù)據(jù)只能由master進(jìn)行更新,master相當(dāng)于是集群的大腦。

ClusterState
集群中的每個節(jié)點(diǎn)都會在內(nèi)存中維護(hù)一個當(dāng)前的ClusterState,表示當(dāng)前集群的各種狀態(tài)。ClusterState中包含一個MetaData的結(jié)構(gòu),MetaData中存儲的內(nèi)容更符合meta的特征,而且需要持久化的信息都在MetaData中,此外的一些變量可以認(rèn)為是一些臨時狀態(tài),是集群運(yùn)行中動態(tài)構(gòu)建出來的。

ClusterState內(nèi)容包括:
    long version: 當(dāng)前版本號,每次更新加1
    String stateUUID:該state對應(yīng)的唯一id
    RoutingTable routingTable:所有index的路由表
    DiscoveryNodes nodes:當(dāng)前集群節(jié)點(diǎn)
    MetaData metaData:集群的meta數(shù)據(jù)
    ClusterBlocks blocks:用于屏蔽某些操作
    ImmutableOpenMap customs: 自定義配置
    ClusterName clusterName:集群名

MetaData

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

MetaData中需要持久化的包括:
    String clusterUUID:集群的唯一id。
    long version:當(dāng)前版本號,每次更新加1
    Settings persistentSettings:持久化的集群設(shè)置
    ImmutableOpenMap indices: 所有Index的Meta
    ImmutableOpenMap templates:所有模版的Meta
    ImmutableOpenMap customs: 自定義配置

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

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

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

2. Meta的存儲

首先,在啟動ES的一個節(jié)點(diǎn)時,會配置一個data目錄,例如下面這個目錄。該節(jié)點(diǎn)只有一個單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進(jìn)程會把Meta和Data都寫入這個目錄中,其中目錄名為_state的代表該目錄存儲的是meta文件,根據(jù)文件層級的不同,共有3種meta的存儲:

nodes/0/_state/:

這層目錄在節(jié)點(diǎn)級別,該目錄下的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關(guān)聯(lián)不大,本文不做過多介紹。

可以看到,集群相關(guān)的MetaData和Index的MetaData是在不同的目錄中存儲的。另外,集群相關(guān)的Meta會在所有的MasterNode和DataNode上存儲,而Index的Meta會在所有的MasterNode和存儲了該Index數(shù)據(jù)的DataNode上存儲。

這里有個問題是,MetaData是由Master管理的,為什么DataNode上也要保存MetaData呢?主要原因是考慮到數(shù)據(jù)的安全性,很多用戶沒有考慮Master節(jié)點(diǎn)的高可用和數(shù)據(jù)高可靠,在部署ES集群時只配置了一個MasterNode,如果這個節(jié)點(diǎn)不可用,就會出現(xiàn)Meta丟失,后果非常嚴(yán)重。

3. Meta的恢復(fù)

假設(shè)ES集群重啟了,那么所有進(jìn)程都沒有了之前的Meta信息,需要有一個角色來恢復(fù)Meta,這個角色就是Master。所以ES集群需要先進(jìn)行Master選舉,選出Master后,才會進(jìn)行故障恢復(fù)。

當(dāng)Master選舉出來后,Master進(jìn)程還會等待一些條件,比如集群當(dāng)前的節(jié)點(diǎn)數(shù)大于某個數(shù)目等,這是避免有些DataNode還沒有連上來,造成不必要的數(shù)據(jù)恢復(fù)等。

當(dāng)Master進(jìn)程決定進(jìn)行恢復(fù)Meta時,它會向集群中的MasterNode和DataNode請求其機(jī)器上的MetaData。對于集群的Meta,選擇其中version最大的版本。對于每個Index的Meta,也選擇其中最大的版本。然后將集群的Meta和每個Index的Meta再組合起來,構(gòu)成當(dāng)前的最新Meta。

ClusterState的更新流程

現(xiàn)在我們開始分析ClusterState的更新流程,并通過這個流程來看ES如何保證Meta更新的一致性。

1. master進(jìn)程內(nèi)不同線程更改ClusterState時的原子性保證

首先,master進(jìn)程內(nèi)不同線程更改ClusterState時要保證是原子的。試想一下這個場景,有兩個線程都在修改ClusterState,各自更改其中的一部分。假如沒有任何并發(fā)的保護(hù),那么最后提交的線程可能就會覆蓋掉前一個線程的修改,或者產(chǎn)生不符合條件的狀態(tài)變更的發(fā)生。

ES解決這個問題的方式是,每次需要更新ClusterState時提交一個Task給MasterService,MasterService中只使用一個線程來串行處理這些Task,每次處理時把當(dāng)前的ClusterState作為Task中execute函數(shù)的參數(shù)。即保證了所有的Task都是在currentClusterState的基礎(chǔ)上進(jìn)行更改,然后不同的Task是串行執(zhí)行的。

2. ClusterState更改如何保證一旦commit,后續(xù)就一定會在此基礎(chǔ)上commit,不會回退

這里是為了解決這樣一個問題,我們知道,新的Meta一旦在某個節(jié)點(diǎn)上commit,那么這個節(jié)點(diǎn)就會執(zhí)行相應(yīng)的操作,比如刪除某個Shard等,這樣的操作是不可回退的。而假如此時Master節(jié)點(diǎn)掛掉了,新產(chǎn)生的Master一定要在新的Meta上進(jìn)行更改,不能出現(xiàn)回退,否則就會出現(xiàn)Meta回退了但是操作無法回退的情況。本質(zhì)上就是Meta更新沒有保證一致性。

早期的ES版本沒有解決這個問題,后來引入了兩階段提交的方式(Add two phased commit to Cluster State publishing)。所謂的兩階段提交,是把Master發(fā)布ClusterState分成兩步,第一步是向所有節(jié)點(diǎn)send最新的ClusterState,當(dāng)有超過半數(shù)的master節(jié)點(diǎn)返回ack時,再發(fā)送commit請求,要求節(jié)點(diǎn)commit接收到的ClusterState。如果沒有超過半數(shù)的節(jié)點(diǎn)返回ack,那么認(rèn)為本次發(fā)布失敗,同時退出master狀態(tài),執(zhí)行rejoin重新加入集群。

兩階段提交可以解決部分一致性問題,比如以下這種場景:

NodeA本來是Master節(jié)點(diǎn),但由于某些原因NodeB成了新的Master節(jié)點(diǎn),而NodeA由于探測不及時還未發(fā)現(xiàn)。

NodeA認(rèn)為自己仍然是Master,于是照常發(fā)布新的ClusterState。

由于此時NodeB是Master,說明超過半數(shù)的Master節(jié)點(diǎn)認(rèn)為NodeB才是新的Master,于是超過半數(shù)的Master節(jié)點(diǎn)不會返回ack給NodeA。

NodeA收集不到足夠的ack,于是本次發(fā)布失敗,同時退出master狀態(tài)。

新的ClusterState不會在任何節(jié)點(diǎn)上commit,于是沒有不一致發(fā)生。

但是這種方式也存在很多一致性的問題,我們下一節(jié)來具體分析。

3. 一致性問題分析

ES中,Master發(fā)送commit的原則是只要有超過半數(shù)MasterNode(master-eligible node)接收了新的ClusterState就發(fā)送commit。那么實(shí)際上就是認(rèn)為只要超過半數(shù)節(jié)點(diǎn)接收了新的ClusterState,這個ClusterState就一定可以被commit,不會在各種場景下回退。

問題1

第一階段master節(jié)點(diǎn)send新的ClusterState,接收到的節(jié)點(diǎn)只是把新的ClusterState放入內(nèi)存一個隊(duì)列中,就會返回ack。這個過程沒有持久化,所以當(dāng)master接收到超過半數(shù)的ack后,也不能認(rèn)為這些節(jié)點(diǎn)上都有新的ClusterState了。

問題2

如果master在commit階段,只commit了少數(shù)幾個節(jié)點(diǎn)就出現(xiàn)了網(wǎng)絡(luò)分區(qū),將master與這幾個少數(shù)節(jié)點(diǎn)分在了一起,其他節(jié)點(diǎn)可以互相訪問。此時其他節(jié)點(diǎn)構(gòu)成多數(shù)派,會選舉出新的master,由于這部分節(jié)點(diǎn)中沒有任何節(jié)點(diǎn)commit了新的ClusterState,所以新的master仍會使用更新前的ClusterState,造成Meta不一致。

ES官方仍在追蹤這個bug:

https://www.elastic.co/guide/en/elasticsearch/resiliency/current/index.html

Repeated network partitions can cause cluster state updates to be lost (STATUS: ONGOING)
...This problem is mostly fixed by #20384 (v5.0.0), which takes committed cluster state updates into account during master election. This considerably reduces the chance of this rare problem occurring but does not fully mitigate it. If the second partition happens concurrently with a cluster state update and blocks the cluster state commit message from reaching a majority of nodes, it may be that the in flight update will be lost. If the now-isolated master can still acknowledge the cluster state update to the client this will amount to the loss of an acknowledged change. Fixing that last scenario needs considerable work. We are currently working on it but have no ETA yet.

什么情況下會有問題
在兩階段提交中,很重要的一個條件是,“超過半數(shù)節(jié)點(diǎn)返回ack,表示接收了這個ClusterState”,這個條件并不能帶來任何保證。一方面接收ClusterState并不會持久化,另一方面接收了ClusterState也不會對未來選舉新Master產(chǎn)生任何干擾,因?yàn)檫x舉時只考慮已經(jīng)commit的ClusterState。

在兩階段過程中,只到Master在超過半數(shù)MasterNode(master-eligible node)上commit了新的ClusterState,并且這些節(jié)點(diǎn)都完成了新ClusterState的持久化時,才到達(dá)一個安全的狀態(tài)。在開始commit到達(dá)到這個狀態(tài)之間,如果Master發(fā)送故障,就可能導(dǎo)致Meta發(fā)生不一致。

如何解決當(dāng)前的一致性問題

既然ES目前Meta更新存在一些一致性問題,那么我們來腦洞一下,如何解決這些一致性問題呢?

1. 實(shí)現(xiàn)一個標(biāo)準(zhǔn)的一致性算法,比如raft
第一種方式是實(shí)現(xiàn)一個標(biāo)準(zhǔn)的一致性算法,比如raft。在上一篇中,我們也比較了ES的選舉算法與raft算法的異同,下面我們繼續(xù)比較一下ES的meta更新流程與raft的日志復(fù)制流程。

相同點(diǎn):

都是在得到超過半數(shù)節(jié)點(diǎn)應(yīng)答之后,執(zhí)行commit。
不同點(diǎn):

raft算法中,follower接收到日志后就會進(jìn)行持久化,寫到磁盤上。ES中,節(jié)點(diǎn)接收到ClusterState只是放到內(nèi)存中的一個隊(duì)列中即返回,并不持久化。

raft算法可以保證在超過半數(shù)節(jié)點(diǎn)應(yīng)答之后,這條日志一定可以被commit,而ES中沒有保證這一點(diǎn),目前還存在一致性問題。

通過上面的比較,我們再次看到,ES中meta更新的算法與raft相比很相似,raft使用了更多的機(jī)制來保證一致性,而ES還存在一些問題。用ES官方的話來說,fix這些問題還需要大量的工作(considerable work)。

2. 借助額外的組件保證meta一致性
比如使用Zookeeper來保存Meta,用Zookeeper來保證Meta的一致性。這樣可以解決一致性的問題,但是性能的問題還需要再評估一下,比如Meta是否會過大而導(dǎo)致不保存在Zookeeper中,每次請求全量Meta還是Diff等。

3. 使用共享存儲來保存Meta
首先保證不會出現(xiàn)腦裂,然后可以使用共享存儲來保存Meta,解決Meta一致性的問題。這種方式會引入一個共享存儲,這個存儲系統(tǒng)需要具備高可靠、高可用特征。

小結(jié)

作為Elasticsearch分布式一致性原理系列的第二篇,本文主要介紹了ES集群中Master節(jié)點(diǎn)發(fā)布Meta更新的流程,分析了其中的一致性問題。此外還介紹了Meta數(shù)據(jù)的組成和存儲方式等。下一篇文章會分析ES中如何保證數(shù)據(jù)的一致性,介紹其寫入流程和算法模型等。

詳情請閱讀原文

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/17712.html

相關(guān)文章

  • Elasticsearch分布一致原理剖析()-Meta

    摘要:前言分布式一致性原理剖析系列將會對的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式原理以及其存在的問題等基于版本。中需要持久化的包括當(dāng)前版本號,每次更新加。收集不到足夠的,于是本次發(fā)布失敗,同時退出狀態(tài)。 前言Elasticsearch分布式一致性原理剖析系列將會對Elasticsearch的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式、原理以及其存在的問題等(基于6.2版本)。前一...

    TIGERB 評論0 收藏0
  • Elasticsearch分布一致原理剖析()-Meta

    摘要:前言分布式一致性原理剖析系列將會對的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式原理以及其存在的問題等基于版本。中需要持久化的包括當(dāng)前版本號,每次更新加。收集不到足夠的,于是本次發(fā)布失敗,同時退出狀態(tài)。 前言Elasticsearch分布式一致性原理剖析系列將會對Elasticsearch的分布式一致性原理進(jìn)行詳細(xì)的剖析,介紹其實(shí)現(xiàn)方式、原理以及其存在的問題等(基于6.2版本)。前一...

    FrancisSoung 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<