Elasticsearch Recovery詳解

轉自:

http://blog.csdn.net/u012450329/article/details/52881045


Elasticsearch Recovery詳解

基礎知識點


在Eleasticsearch中recovery指的就是一個索引的分片分配到另外一個節點的過程;一般在快照恢復、索引副本數變更、節點故障、節點重啓時發生。由於master保存整個集羣的狀態信息,因此可以判斷出哪些shard需要做再分配,以及分配到哪個結點,例如:
  1. 如果某個shard主分片在,副分片所在結點掛了,那麼選擇另外一個可用結點,將副分片分配(allocate)上去,然後進行主從分片的複製。
  2. 如果某個shard的主分片所在結點掛了,副分片還在,那麼將副分片升級爲主分片,然後做主從分片複製。
  3. 如果某個shard的主副分片所在結點都掛了,則暫時無法恢復,等待持有相關數據的結點重新加入集羣后,從該結點上恢復主分片,再選擇另外的結點複製副分片。
 
正常情況下,我們可以通過ES的health的API接口,查看整個集羣的健康狀態和整個集羣數據的完整性:
EsHealth.png

狀態及含義如下:
  • 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.recover_after_nodes
gateway.recover_after_master_nodes
gateway.recover_after_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:
EsNone.png

然後在節點重啓完成加入集羣后,再重新打開:
EsAll.png

這樣在節點重啓完成後,儘量多的從本地直接恢復數據。

但是在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幾乎無法完成 (issue #9226)  。因此實際使用中如果遇到問題,最好在Github的issue list裏搜索一下,看是否使用的版本有其他人反映同樣的問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章