標籤:

CaseStudy:ES索引損壞

前言

上個月的一個CaseStudy,之前已經放在內部文檔里了,這裡放在知乎上,希望和大家一起探討學習。

眾所周知,計算機系統的開發,是絕無可能沒有BUG的。有BUG不可怕(至少對技術來說),我們記錄BUG,回望BUG產生的原因,追本溯源,進而加強相關機制的修補,可以防範同樣的位置摔倒,也可以在對應的位置學習相關的經驗,從而提升技術人員的實力

下面就來看看故障的經過、原因、修復辦法、後續的改進

故障經過

某日下午4:05,CEO反應有的商品搜索不出

某日下午4:13,我開始檢查ES索引問題,發現索引中出現了no_shard_available_action_exception錯誤導致的查不到

某日下午4:44,確認是索引損壞,確定當時有6/78的分片損壞,開始嘗試修復索引

某日下午4:56,確認問題出現自某日-2天上午7點42分

某日下午5:14分,發現「重新進行失敗的分片 」這個操作我們沒有許可權,提交AWS 技術支持case

——————一晚上沒回復————

某日+1天 上午8點 AWS技術支持要求給出es節點和索引狀態狀態

某日+1天 上午9:47 我回復了他

某日+1天 上午12:11 他回復了解決方案:拷貝索引,刪除原有索引並移動回去

某日+1天 下午02:52: 我回復他這個操作會導致業務停止,無法接受,並且要求他給出分片損壞的原因。

某日+1天 下午04:47 他回復了原因(詳情見故障原因)並且表示除了這個辦法還可以增加機器節點,考慮了一下增加節點要多交錢,我決定遷移舊索引,調低分片數量,只用新索引,舊的就不用了

某日+1天 下午05:58 索引數據、應用程序遷移完成。老的索引觀察後刪除了,並且添加了alias,重定向對原來索引的訪問,以防止還有應用程序遺漏

故障期間7%的商品受影響,無法被搜索到

故障原因

我們之前創建的索引,都設置了分片數量(number_of_shards)=5,而我們的es集群中有5個主節點,5個數據節點,在es的優化策略中,會考慮每個節點的資源均衡分配。我們設置的分片數量為5個,首先數據是不會被分至主節點的,當數據節點的分片需要再均衡的時候,會發現無法移動(剛好填滿了),因此造成了分片失敗,新到來的數據無法被索引

當然,這個優化策略是默認的,不過AWS集群的這些配置,都是不能被修改的

原回復:

According to Elasticsearchs optimization, they will not allocate both primary and its replica in the same node. In your case, when you have five nodes with five primaries and two replicas per primaries. In addition, the optimizer has to take care of the resource balancing, and let the resources get evenly distributed. It would increase the chance of unassigned shards though you still have plenty of resources but not enough data nodes. Hence, the solution for this error code may either try to add more nodes or decrease the shard count firstly. Since the delete index is not applicable to you, you may consider to add more nodes.

Q:是不是減少分片數量可以極大減輕這種情況的發生?

A: 是的

for your second question, the answer is yes. The symptom may be mitigated if there are less shards or more data nodes available in the cluster.

Q:減少分片數量會導致其他故障嗎?

A:按照AWS技術支持的文檔:

aws.amazon.com/cn/blogs

不會,並且一個分片也是可以的。

Don』t be afraid of using a single shard!

If you have less than 30 GB of data in your index, you should use a single shard for your index. Some people have a gut feeling that 「more is better.」 Resist the temptation! Shards are both computational and storage entities. Each shard you add to an index distributes the processing of requests for that index across an additional CPU. Performance decreases because you』ll be using more processors than needed, requiring extra computation to manage and combine the results. You will also add network overhead for the scatter-gather of the query and responses.

不要害怕使用一個分片

如果索引中的數據少於30 GB,則應為索引使用單個分片。 有些人有一種「越多越好」的直覺,需要抵制這種誘惑! 分片既是計算又是存儲實體。 添加到索引中的每個分片會通過另外一個CPU分配對該索引的處理請求。 性能將會因為您使用比所需更多的處理器而下降,因為ES需要額外的計算來管理和組合結果。

您還將為查詢和響應的分散收集添加網路開銷。

據此,我調整了後續新建的索引的分片數量,並使用reindex命令拷貝老索引至新索引

補充知識:ES分片

ES作為搜索引擎,有兩個工作:

  1. 從一組文檔創建一個索引。->存儲
  2. 搜索該索引來計算最好的匹配文檔。->計算

如果索引足夠小,則單個機器上的單個數據結構可以輕鬆存儲該索引。

對於較大的文檔集,在單個機器不足以容納索引的情況下,或者在單個機器無法計算您的搜索結果的情況下,索引被拆分成多個部分。這些碎片在Elasticsearch中稱為分片(shard)。每個文檔都被路由到一個分片,默認情況下,是通過使用該文檔ID的hash散列來計算分片的路由。

分片既是一個存儲單位,也是一個計算單位。 Elasticsearch獨立地將分片部署到集群中的實例,以並行化索引的存儲和處理。它彈性地做到這一點(因此名為「Elasticsearch」的「彈性」)。如果將更多實例添加到集群,Amazon Elasticsearch Service會自動重新平衡群集的分片,並在實例之間移動它們。

作為存儲單元,分片是彼此不同的。設置在一個分片中的文檔不會與其他分片中設置的文檔重疊。這種方法使碎片獨立存儲。

作為計算單位,分片也是彼此不同的。每個分片都是Apache Lucene索引的一個實例,它計算所保存文檔的結果。由於所有分片都包含索引,因此它們必須一起工作來處理每個查詢並更新該索引的請求。為了處理查詢,Elasticsearch將查詢路由到索引中的所有分片。每個分片在本地計算其響應,然後將這些響應匯總為最終響應。為了處理寫入請求(文檔添加或對現有文檔的更新),Elasticsearch將請求路由到適當的分片

Elasticsearch有兩種不同的分片類型:主分片和副本分片

主分片首先接收所有寫入。 它將新文檔傳遞給所有副本分片進行索引。 默認情況下,在返回成功給調用者之前,它會等待副本確認寫入。 主資料庫和副本資料庫是數據的冗餘存儲,因此可以防範集群中實例的丟失和損壞。

上圖所示的集群有三個實例,兩個索引:綠色和淺藍色,每個索引有三個分片,其中的主分片用紅框標了起來,每個索引由一個副本,沒標紅框的那個。Elasticsearch根據許多規則將分片映射到實例。 最基本的規則是主和副本分片永遠不會放在同一個實例上。

可以看到的是,這次的case其實就是實例數量和副本分片數量等同,這意味著每個實例上都有一份副本分片,但這也意味著如果ES將要進行資源的重新調配時,整個集群中不會有合理的空間以供移動,因此會導致調配失敗

故障改進

Q:為什麼故障沒有及時發現,如何解決

A:ES上因為AWS日誌報警要收費,所以之前沒有加報警。已經添加了Watchlog報警。

Q:為什麼故障解決時間這麼長?是否有改進的餘地

A:

  1. 之前沒有交接對ES的運維,所以花了一些時間尋找ES機器,並找到問題的原因。需要對ES相關運維知識加深了解
  2. AWS的回復稍慢,如果是更嚴重的線上事故,技術支持的回復速度在小時級別。所以不能對AWS的技術支持太過依賴,比如這個問題,如果我了解分片數量的問題,早開始遷移索引,可以讓故障時間減少一天。而且AWS的case真的很貴,按機器的3%的費用或最低50刀一個月。。

Q:有哪些後續需要注意的

A: 控制分片數量和集群內的實例數,養成「分片數量不是越多越好」的觀念

參考文獻

我需要多少數據實例

我需要多少分片

reindex 複製數據

aliases 索引別名

cat 狀態檢修命令集

集群分配問題檢修 和此次的錯誤:

"unassigned_info": { "reason": "ALLOCATION_FAILED", "at": "2017-12-15T23:20:45.844Z", "failed_allocation_attempts": 5, "details": "failed to create shard, failure IOException[failed to obtain in-memory shard lock]; nested: ShardLockObtainFailedException[[item_search_1011][2]: obtaining shard lock timed out after 5000ms]; ", "last_allocation_status": "no_valid_shard_copy" }, "can_allocate": "no_valid_shard_copy", "allocate_explanation": "cannot allocate because a previous copy of the primary shard existed but can no longer be found on the nodes in the cluster"

集群重路由 以及最後說到的可以用retry_failed參數指定重新生成未分配的分片,AWS上禁了集群相關操作,所以AWS上沒用,並且沒有解決分片數量問題的時候,用這個也沒有用


推薦閱讀:

elasticsearch,我用ik分詞,搜索"寶馬2012",怎樣只查出即包含「寶馬」又包含「2012」的文章?
Elastic Stack 5.0升級踩坑記
多個ElasticSearch Cluster的一致性問題
日誌分析的模式發現功能實現(1)
Elasticsearch:文檔的CRUD操作API(第三篇)

TAG:Elasticsearch |