天天看點

Elasticsearch叢集啟動流程選舉主節點選舉叢集元資訊allocation過程資料恢複

文章目錄

  • 選舉主節點
  • 選舉叢集元資訊
  • allocation過程
    • 選主分片
    • 選副分片
  • 資料恢複
    • 主分片recovery
    • 副分片recovery

叢集啟動過程要經曆選舉主節點、主分片、資料恢複等重要階段。

Elasticsearch叢集啟動流程選舉主節點選舉叢集元資訊allocation過程資料恢複

選舉主節點

叢集啟動的第一件事是選擇主節點,選主之後的流程由主節點觸發。ES的選主算法是基于Bully算法的改進,主要思路是對節點ID排序,取ID值最大的節點作為Master,每個節點都運作這個流程。在實作上被分解為兩步:先确定唯一的、大家公認的主節點,再想辦法把最新的機器中繼資料複制到選舉出的主節點上。基于節點ID排序的簡單選舉算法有三個附加約定條件:

  1. 參選人數需要過半,達到quorum(多數)。
  2. 得票數需過半。
  3. 當探測到節點離開事件時,必須判斷目前節點數是否過半。如果達不到quorum,則放棄Master身份,重新加入叢集。如果不這麼做,則可能産生雙主,俗稱腦裂。

叢集并不知道自己共有多少個節點,quorum值從配置中讀取,我們需要設定配置項:

discovery.zen.minimum_master_nodes = master節點數/2 + 1

選舉叢集元資訊

被選出的Master和叢集元資訊的新舊程度沒有關系。是以Master的第一個任務是選舉元資訊,讓各節點把各自存儲的元資訊發過來,根據版本号确定最新的元資訊,然後把這個資訊廣播下去,這樣叢集的所有節點都有了最新的元資訊。為了叢集一緻性,參與選舉的元資訊數量需要過半,Master釋出叢集狀态成功的規則也是等待釋出成功的節點數過半。在選舉過程中,不接受新節點的加入請求。

叢集元資訊不包含哪個shard存于哪個節點這種資訊。這種資訊以節點磁盤存儲的為準,需要上報。為什麼呢?因為讀寫流程是不經過Master的,Master不知道各shard副本直接的資料差異。HDFS也有類似的機制,block資訊依賴于DataNode的上報。

allocation過程

叢集元資訊選舉完畢後,Master釋出首次叢集狀态,然後開始選舉shard級元資訊。選舉shard級元資訊,建構内容路由表,是在allocation子產品完成的。在初始階段,所有的shard都處于UNASSIGNED(未配置設定)狀态。ES中通過配置設定過程決定哪個分片位于哪個節點,重構内容路由表。此時,首先要做的是配置設定主分片。

allocation過程中允許新啟動的節點加入叢集。

選主分片

所有的分片配置設定工作都是Master來做的,它向叢集的所有節點詢問:大家把某分片的元資訊發給我。然後,Master等待所有的請求傳回,然後根據某種政策選一個分片作為主分片(這種詢問量=

shard數 * 節點數

,是以我們最好控制shard的總規模别太大)。

現在有了分片的多份資訊,在ES 5.x以下的版本,通過對比shard級元資訊的版本号來決定主分片,但這可能會将資料不是最新的分片選為主分片。是以ES 5.x開始實施一種新的政策:給每個shard都設定一個UUID,并在叢集級的元資訊中記錄哪個shard是最新的(因為ES是先寫主分片,再由主分片節點轉發請求去寫副分片,是以主分片所在節點的資料肯定是最新的,如果它轉發失敗了,則要求Master删除那個節點),然後通過叢集級元資訊中記錄的“最新主分片的清單”來确定主分片:節點彙報資訊中存在該分片,并且這個清單中也存在。

如果叢集設定了:“cluster.routing.allocation.enable”: “none”。禁止配置設定分片,叢集仍會強制配置設定主分片。是以,在設定了上述選項的情況下,叢集重新開機後的狀态為Yellow,而非Red。

選副分片

主分片選舉完成後,從上一個過程彙總的shard資訊中選擇一個副本作為副分片。如果彙總資訊中不存在,則配置設定一個全新副本的操作依賴于延遲配置項:

index.unassigned.node_left.delayed_timeout

(通常以天為機關)。

資料恢複

分片配置設定成功後進入recovery流程。主分片的recovery不會等待其副分片配置設定成功才開始recovery。它們是獨立的流程,隻是副分片的recovery需要主分片恢複完畢才開始。

為什麼需要recovery?對于主分片來說,可能有一些資料沒來得及刷盤;對于副分片來說,一是沒刷盤,二是主分片寫完了,副分片還沒來得及寫,主副分片資料不一緻。

主分片recovery

由于每次寫操作都會記錄事務日志(translog),是以将最後一次送出(Lucene的一次送出就是一次fsync刷盤的過程)之後的translog進行重放,建立Lucene索引,如此完成主分片的recovery。

副分片recovery

副分片需要恢複成與主分片一緻,同時,恢複期間允許新的索引操作。在6.0版本中,恢複分成兩階段執行。

  • phase1:在主分片所在節點,擷取translog保留鎖,從擷取保留鎖開始,會保留translog不受其刷盤清空的影響。然後調用Lucene接口把shard做快照,這是已經刷磁盤中的分片資料。把這些shard資料複制到副本節點。在phase1完畢前,會向副分片節點發送告知對方啟動engine,在phase2開始之前,副分片就可以正常處理寫請求了。
  • phase2:對translog做快照,這個快照裡包含從phase1開始,到執行translog快照期間的新增索引。将這些translog發送到副分片所在節點進行重放。

第一階段尤其漫長,因為它需要從主分片拉取全量的資料。在ES 6.x中,對第一階段再次優化:标記每個操作。在正常的寫操作中,每次寫入成功的操作都配置設定一個序号,通過對比序号就可以計算出差異範圍,在實作方式上,添加了global checkpoint和local checkpoint,主分片負責維護global checkpoint,代表所有分片都已寫入這個序号的位置,local checkpoint代表目前分片已寫入成功的最新位置,恢複時通過對比兩個序列号,計算出缺失的資料範圍,然後通過translog重放這部分資料,同時translog會為此保留更長的時間。是以,有兩個機會可以跳過副分片恢複的phase1:基于SequenceNumber,從主分片節點的translog恢複資料;主副兩分片有相同的syncid且doc數相同,可以跳過phase1。

由于需要支援恢複期間的新增寫操作(讓ES的可用性更強),這兩個階段中需要重點關注以下幾個問題。

  • 分片資料完整性:如何做到副分片不丢資料?第二階段的translog快照包含第一階段所有的新增操作。那麼第一階段執行期間如果發生“Lucene commit”(将檔案系統寫緩沖中的資料刷盤,并清空translog),清除translog怎麼辦?從6.0版本開始,引入TranslogDeletionPolicy的概念,它将translog做一個快照來保持translog不被清理。
  • 資料一緻性:在副分片節點,重放translog時,phase1和phase2之間的寫操作與phase2重放操作之間的時序錯誤和沖突,通過寫流程中進行異常處理,對比版本号來過濾掉過期操作。這樣,時序上存在錯誤的操作被忽略,對于特定的doc,隻有最新一次操作生效,保證了主副分片一緻。

繼續閱讀