首頁 > 軟體

Elasticsearch Recovery索引分片分配詳解

2022-04-19 19:00:24

基礎知識點

在Eleasticsearch中recovery指的就是一個索引的分片分配到另外一個節點的過程;一般在快照恢復、索引副本數變更、節點故障、節點重啟時發生。由於master儲存整個叢集的狀態資訊,因此可以判斷出哪些shard需要做再分配,以及分配到哪個結點,例如:

如果某個shard主分片在,副分片所在結點掛了,那麼選擇另外一個可用結點,將副分片分配(allocate)上去,然後進行主從分片的複製。

如果某個shard的主分片所在結點掛了,副分片還在,那麼將副分片升級為主分片,然後做主從分片複製。

如果某個shard的主副分片所在結點都掛了,則暫時無法恢復,等待持有相關資料的結點重新加入叢集後,從該結點上恢復主分片,再選擇另外的結點複製副分片。  

正常情況下,我們可以通過ES的health的API介面,檢視整個叢集的健康狀態和整個叢集資料的完整性:

狀態及含義如下:

green: 所有的shard主副分片都是正常的;

yellow: 所有shard的主分片都完好,部分副分片沒有或者不完整,資料完整性依然完好;

red: 某些shard的主副分片都沒有了,對應的索引資料不完整。  

recovery過程要消耗額外的資源,CPU、記憶體、結點之間的網路頻寬等等。 這些額外的資源消耗,有可能會導致叢集的服務效能下降,或者一部分功能暫時不可用。瞭解一些recovery的過程和相關的設定引數,對於減小recovery帶來的資源消耗,加快叢集恢復過程都是很有幫助的。

減少叢集Full Restart造成的資料來回拷貝

ES叢集可能會有整體重啟的情況,比如需要升級硬體、升級作業系統或者升級ES大版本。重啟所有結點可能帶來的一個問題: 某些結點可能先於其他結點加入叢集, 先加入叢集的結點可能已經可以選舉好master,並立即啟動了recovery的過程,由於這個時候整個叢集資料還不完整,master會指示一些結點之間相互開始複製資料。 那些晚到的結點,一旦發現原生的資料已經被複制到其他結點,則直接刪除掉本地“失效”的資料。 當整個叢集恢復完畢後,資料分佈不均衡,顯然是不均衡的,master會觸發rebalance過程,將資料在節點之間挪動。整個過程無謂消耗了大量的網路流量;合理設定recovery相關引數則可以防範這種問題的發生。

gateway.expected_nodes
gateway.expected_master_nodes
gateway.expected_data_nodes

以上三個引數是說叢集裡一旦有多少個節點就立即開始recovery過程。 不同之處在於,第一個引數指的是master或者data都算在內,而後面兩個引數則分指master和data node。

在期待的節點數條件滿足之前, recovery過程會等待gateway.recover_after_time (預設5分鐘) 這麼長時間,一旦等待超時,則會根據以下條件判斷是否啟動:

gateway.expected_nodes
gateway.expected_master_nodes
gateway.expected_data_nodes

舉例來說,對於一個有10個data node的叢集,如果有以下的設定:

gateway.expected_data_nodes: 10
gateway.recover_after_time: 5m
gateway.recover_after_data_nodes: 8

那麼叢集5分鐘以內10個data node都加入了,或者5分鐘以後8個以上的data node加入了,都會立即啟動recovery過程。

減少主副本之間的資料複製

如果不是full restart,而是重啟單個data node,仍然會造成資料在不同結點之間來回複製。為避免這個問題,可以在重啟之前,先關閉叢集的shard allocation:

然後在節點重啟完成加入叢集後,再重新開啟:

這樣在節點重啟完成後,儘量多的從本地直接恢復資料。

但是在ES1.6版本之前,即使做了以上措施,仍然會發現有大量主副本之間的資料拷貝。從表面去看,這點很讓人不能理解。

主副本資料完全一致,ES應該直接從副本本地恢復資料就好了,為什麼要重新從主片再複製一遍呢? 原因在於recovery是簡單對比主副本的segment file來判斷哪些資料一致可以本地恢復,哪些不一致需要遠端拷貝的。

而不同節點的segment merge是完全獨立執行的,可能導致主副本merge的深度不完全一樣,從而造成即使檔案集完全一樣,產生的segment file卻不完全一樣。

為了解決這個問題,ES1.6版本以後加入了synced flush的新特性。 對於5分鐘沒有更新過的shard,會自動synced flush一下,實質是為對應的shard加了一個synced flush ID。這樣當重啟節點的時候,先對比一下shard的synced flush ID,就可以知道兩個shard是否完全相同,避免了不必要的segment file拷貝,極大加快了冷索引的恢復速度。

需要注意的是synced flush只對冷索引有效,對於熱索引(5分鐘內有更新的索引)沒有作用。 如果重啟的結點包含有熱索引,那麼還是免不了大量的檔案拷貝

。因此在重啟一個結點之前,最好按照以下步驟執行,recovery幾乎可以瞬間完成:

  1. 暫停資料寫入程式
  2. 關閉叢集shard allocation
  3. 手動執行POST /_flush/synced
  4. 重啟節點
  5. 重新開啟叢集shard allocation 
  6. 等待recovery完成,叢集health status變成green
  7. 重新開啟資料寫入程式  

特大熱索引為何恢復慢

對於冷索引,由於資料不再更新,利用synced flush特性,可以快速直接從本地恢復資料。 而對於熱索引,特別是shard很大的熱索引,;除了synced flush派不上用場需要大量跨節點拷貝segment file以外,translog recovery是導致慢的更重要的原因。

從主片恢復資料到副片需要經歷3個階段:

  1. 對主片上的segment file做一個快照,然後拷貝到複製片分配到的結點。資料拷貝期間,不會阻塞索引請求,新增索引操作記錄到translog裡。
  2. 對translog做一個快照,此快照包含第一階段新增的索引請求,然後重放快照裡的索引操作。此階段仍然不阻塞索引請求,新增索引操作記錄到translog裡。
  3. 為了能達到主副片完全同步,阻塞掉新索引請求,然後重放階段二新增的translog操作。  

可見,在recovery完成之前,translog是不能夠被清除掉的(禁用掉正常運作期間後臺的flush操作)。

如果shard比較大,第一階段耗時很長,會導致此階段產生的translog很大。重放translog比起簡單的檔案拷貝耗時要長得多,因此第二階段的translog耗時也會顯著增加。

等到第三階段,需要重放的translog可能會比第二階段還要多。 而第三階段是會阻塞新索引寫入的,在對寫入實時性要求很高的場合,就會非常影響使用者體驗。

因此,要加快大的熱索引恢復速度,最好的方式是遵從上一節提到的方法: 暫停新資料寫入,手動sync flush,等待資料恢復完成後,重新開啟資料寫入,這樣可以將資料延遲影響可以降到最低。

萬一遇到Recovery慢,想知道進度怎麼辦呢? CAT Recovery API可以顯示詳細的recovery各個階段的狀態。 這個API怎麼用就不在這裡贅述了,參考:  CAT Recovery。

其他Recovery相關的專家級設定

還有其他一些專家級的設定(參見:   recovery)可以影響recovery的速度,但提升速度的代價是更多的資源消耗,因此在生產叢集上調整這些引數需要結合實際情況謹慎調整,一旦影響應用要立即調整回來。

對於搜尋並行量要求高,延遲要求低的場合,預設設定一般就不要去動了。

對於紀錄檔實時分析類對於搜尋延遲要求不高,但對於資料寫入延遲期望比較低的場合,可以適當調大indices.recovery.max_bytes_per_sec,提升recovery速度,減少資料寫入被阻塞的時長。

最後要說的一點是ES的版本迭代很快,對於Recovery的機制也在不斷的優化中。 其中有一些版本甚至引入了一些bug,比如在ES1.4.x有嚴重的translog recovery bug,導致大的索引trans log recovery幾乎無法完成 。

因此實際使用中如果遇到問題,最好在Github的issue list裡搜尋一下,看是否使用的版本有其他人反映同樣的問題。

以上就是Elasticsearch Recovery索引分片分配詳解的詳細內容,更多關於Elasticsearch Recovery索引分片分配的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com