如何在Elasticsearch中解析未分配的分片(unassigned shards)
一、精確定位到有問題的shards
1、查看哪些分片未被分配
curl -XGET localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED
2、如果您運行的是Elasticsearch的5+版本,您還可以使用群集分配說明API來嘗試獲取有關分片分配問題的更多信息:
curl -XGET localhost:9200/_cluster/allocation/explain?pretty
生成的輸出將提供有關群集中某些分片未分配的原因的有用詳細信息:
{"index" : "testing", "shard" : 0, "primary" : false, "current_state" : "unassigned", "unassigned_info" : { "reason" : "INDEX_CREATED", "at" : "2018-04-09T21:48:23.293Z", "last_allocation_status" : "no_attempt" }, "can_allocate" : "no", "allocate_explanation" : "cannot allocate because allocation is not permitted to any of the nodes", "node_allocation_decisions" : [ { "node_id" : "t_DVRrfNS12IMhWvlvcfCQ", "node_name" : "t_DVRrf", "transport_address" : "127.0.0.1:9300", "node_decision" : "no", "weight_ranking" : 1, "deciders" : [ { "decider" : "same_shard","decision" : "NO", "explanation" : "the shard cannot be allocated to the same node on which a copy of the shard already exists" } ] } ] }
二、Elasticsearch中解析未分配的各個原因解析
1、故意分配碎片分配
當節點離開集群時,主節點暫時延遲分片重新分配,以避免在原始節點能夠在特定時間段(默認為一分鐘)內恢復時不必要地在重新平衡分片上浪費資源。如果是這種情況,您的日誌應如下所示:
[TIMESTAMP][INFO][cluster.routing] [MASTER NODE NAME] delaying allocation for [54] unassigned shards, next check in [1m]
解決辦法:動態修改延遲時間
curl -XPUT ‘localhost:9200/<INDEX_NAME>/_settings‘ -d ‘{ "settings": { "index.unassigned.node_left.delayed_timeout": "30s" } }‘
2、分片太多,節點不夠
當節點加入和離開集群時,主節點會自動重新分配分片,確保分片的多個副本未分配給同一節點。換句話說,主節點不會將主分片分配給與其副本相同的節點,也不會將同一分片的兩個副本分配給同一節點。如果沒有足夠的節點來相應地分配分片,則分片可能會停留在未分配狀態。
要避免此問題,請確保使用以下公式初始化群集中的每個索引,每個主分片的副本數少於群集中的節點數:
N >= R + 1
其中N是群集中的節點數,R是群集中所有索引的最大分片復制因子。
在下面的屏幕截圖中,many-shards
索引存儲在四個主分片上,每個主分片有四個副本。索引的20個分片中有8個未分配,因為我們的群集只包含三個節點。尚未分配每個主分片的兩個副本,因為三個節點中的每個節點都已包含該分片的副本。
解決辦法:可以向群集添加更多數據節點或減少副本數。這裏我們通過減少副本數的方式解決:
curl -XPUT ‘localhost:9200/<INDEX_NAME>/_settings‘ -d ‘{"number_of_replicas": 2}‘
減少副本數量後,查看Kopf以查看是否已分配所有分片。
3、加入一個新的節點,需要重新啟用分片分配
在下面的截屏中,一個節點剛加入集群,但尚未分片任何分片
默認情況下,在所有節點上啟用分片分配,但您可能在某些時候禁用了分片分配(例如,為了執行滾動重新啟動),並且忘記重新啟用它。
要啟用分片分配,請更新群集設置API:
curl -XPUT ‘localhost:9200/_cluster/settings‘ -d ‘{ "transient": { "cluster.routing.allocation.enable" : "all" } }‘
4、集群中不在存在分片數據
在這種情況下,constant-updates
索引的主分片0 是未分配的。它可能是在沒有任何副本的節點上創建的(一種用於加速初始索引過程的技術),並且節點在可以復制數據之前離開了集群。主服務器在其全局集群狀態文件中檢測分片,但無法在集群中找到分片的數據。
另一種可能性是節點在重新啟動時可能遇到問題。通常,當節點恢復其與群集的連接時,它會將有關其磁盤分片的信息中繼到主服務器,然後主服務器將這些分片從“未分配”轉換為“已分配/已啟動”。當此過程由於某種原因(例如,節點的存儲已經以某種方式損壞)失敗時,分片可能保持未分配狀態。
在這種情況下,您必須決定如何繼續:嘗試讓原始節點恢復並重新加入群集(並且不強制分配主分片),或者使用Reroute API強制分配分片並使用重新索引丟失的數據原始數據源,或來自備份。
如果您決定分配未分配的主分片,請確保將該"allow_primary": "true"
標誌添加到請求中:
curl -XPOST ‘localhost:9200/_cluster/reroute‘ -d ‘{ "commands" : [ { "allocate" : { "index" : "constant-updates", "shard" : 0, "node": "<NODE_NAME>", "allow_primary": "true" } }] }‘
沒有"allow_primary": "true"
標誌,我們會遇到以下錯誤:
{"error":{"root_cause":[{"type":"remote_transport_exception","reason":"[NODE_NAME][127.0.0.1:9301][cluster:admin/reroute]"}],"type":"illegal_argument_exception","reason":"[allocate] trying to allocate a primary shard [constant-updates][0], which is disabled"},"status":400}
強制分配主分片的警告是你將分配一個“空”分片。如果包含原始主分片數據的節點稍後將重新加入群集,則其數據將被新創建的(空)主分片覆蓋,因為它將被視為數據的“較新”版本。
您現在需要重新索引丟失的數據,或使用快照和還原API從備份快照中盡可能多地還原。
5、磁盤水印低(Low disk watermark)
如果沒有足夠的磁盤空間節點,主節點可能無法分配分片(它不會將分片分配給使用率超過85%的磁盤的節點)。一旦節點達到此磁盤使用級別,或Elasticsearch稱為“低磁盤水印”,將不會為其分配更多分片。
您可以通過查詢cat API來檢查群集中每個節點上的磁盤空間(並查看每個節點上存儲的分片):
curl -s ‘localhost:9200/_cat/allocation?v‘
如果任何特定節點的磁盤空間不足(刪除過時的數據並將其存儲在群集外,添加更多節點,升級硬件等),請參閱此文章以獲取有關如何操作的選項。
如果您的節點具有大磁盤容量,則85%的低水印可能太低。您可以使用群集更新設置API進行更改cluster.routing.allocation.disk.watermark.low
和/或cluster.routing.allocation.disk.watermark.high
。例如,此Stack Overflow線程指出,如果您的節點具有5TB磁盤容量,則可以安全地將低磁盤水印增加到90%:
curl -XPUT ‘localhost:9200/_cluster/settings‘ -d ‘{ "transient": { "cluster.routing.allocation.disk.watermark.low": "90%" } }‘
如果希望在群集重新啟動時保持配置更改,請將“transient”替換為“persistent”,或者在配置文件中更新這些值。您可以選擇使用字節或百分比值來更新這些設置,但請務必記住Elasticsearch文檔中的這一重要說明:“百分比值是指已用磁盤空間,而字節值是指可用磁盤空間。”
如何在Elasticsearch中解析未分配的分片(unassigned shards)