ElasticSearch:未分配的碎片,如何解决?
我有一个ES节点有4个节点:
number_of_replicas: 1 search01 - master: false, data: false search02 - master: true, data: true search03 - master: false, data: true search04 - master: false, data: true
我不得不重新启动search03,当它回来,它重新join群集没有问题,但剩下7个未分配的碎片铺设。
{ "cluster_name" : "tweedle", "status" : "yellow", "timed_out" : false, "number_of_nodes" : 4, "number_of_data_nodes" : 3, "active_primary_shards" : 15, "active_shards" : 23, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 7 }
现在我的群集处于黄色状态。 解决这个问题的最好方法是什么?
- 删除(取消)碎片?
- 将碎片移动到另一个节点?
- 分配碎片到节点?
- 更新'number_of_replicas'为2?
- 还有其他的东西吗?
有趣的是,当添加一个新的索引时,该节点开始工作,并与集群的其余部分打好关系,只留下未分配的碎片。
按照问题:我做错了,导致这种事情发生在第一位? 当一个节点重新启动时,我对这种方式的集群没有太多的信心。
注:如果由于某种原因正在运行单个节点群集,则可能只需执行以下操作:
curl -XPUT 'localhost:9200/_settings' -d ' { "index" : { "number_of_replicas" : 0 } }'
默认情况下,Elasticsearch会dynamic地为节点重新分配分片。 但是,如果您禁用了碎片分配(也许您执行了滚动重新启动并忘记重新启用它),则可以重新启用碎片分配。
# v0.90.x and earlier curl -XPUT 'localhost:9200/_settings' -d '{ "index.routing.allocation.disable_allocation": false }' # v1.0+ curl -XPUT 'localhost:9200/_cluster/settings' -d '{ "transient" : { "cluster.routing.allocation.enable" : "all" } }'
然后,Elasticsearch将正常重新分配碎片。 这可能会很慢,请考虑提高indices.recovery.max_bytes_per_sec
和cluster.routing.allocation.node_concurrent_recoveries
以加快速度。
如果您仍然看到问题,则可能是其他问题,请查看您的Elasticsearch日志中是否有错误。 如果您看到EsRejectedExecutionException
线程池可能太小 。
最后,您可以使用redirectAPI明确地将一个分片重新分配给一个节点。
# Suppose shard 4 of index "my-index" is unassigned, so you want to # assign it to node search03: curl -XPOST 'localhost:9200/_cluster/reroute' -d '{ "commands": [{ "allocate": { "index": "my-index", "shard": 4, "node": "search03", "allow_primary": 1 } }] }'
好的,我已经用ES支持的一些帮助解决了这个问题。 在所有节点(或者您认为是造成问题的原因的节点)上向API发出以下命令:
curl -XPUT 'localhost:9200/<index>/_settings' \ -d '{"index.routing.allocation.disable_allocation": false}'
其中<index>
是您认为是罪魁祸首的索引。 如果你不知道,只需在所有节点上运行:
curl -XPUT 'localhost:9200/_settings' \ -d '{"index.routing.allocation.disable_allocation": false}'
我也将这行添加到我的ymlconfiguration,从那以后,服务器/服务的任何重新启动都没有问题。 碎片立即重新分配。
FWIW,回答一个常见的问题,设置MAX_HEAP_SIZE为30G,除非你的机器的RAM小于60G,在这种情况下,将其设置为可用内存的一半。
这个小bash脚本会蛮力重新分配,你可能会丢失数据。
NODE="YOUR NODE NAME" IFS=$'\n' for line in $(curl -s 'localhost:9200/_cat/shards' | fgrep UNASSIGNED); do INDEX=$(echo $line | (awk '{print $1}')) SHARD=$(echo $line | (awk '{print $2}')) curl -XPOST 'localhost:9200/_cluster/reroute' -d '{ "commands": [ { "allocate": { "index": "'$INDEX'", "shard": '$SHARD', "node": "'$NODE'", "allow_primary": true } } ] }' done
唯一对我有用的是改变number_of_replicas(我有2副本,所以我把它改为1,然后改回2)。
第一:
PUT /myindex/_settings { "index" : { "number_of_replicas" : 1 } }
然后:
PUT /myindex/_settings { "index" : { "number_of_replicas" : 2 } }
(我已经在这个问题上回答了 )
如果下面的configuration设置为all,Elasticsearch会自动分配碎片。 这个configuration可以使用rest api以及 cluster.routing.allocation.enable:all来设置
如果即使在应用下面的configuration之后,es也不能自动分配分片,那么你必须自己强制分配分片。 ES官方链接为此
我写了一个脚本来强制在群集中分配所有未分配的分片。
下面的数组包含你想要平衡未分配的分片的节点列表
#!/bin/bash array=( node1 node2 node3 ) node_counter=0 length=${#array[@]} IFS=$'\n' for line in $(curl -s 'http://127.0.0.1:9200/_cat/shards'| fgrep UNASSIGNED); do INDEX=$(echo $line | (awk '{print $1}')) SHARD=$(echo $line | (awk '{print $2}')) NODE=${array[$node_counter]} echo $NODE curl -XPOST 'http://127.0.0.1:9200/_cluster/reroute' -d '{ "commands": [ { "allocate": { "index": "'$INDEX'", "shard": '$SHARD', "node": "'$NODE'", "allow_primary": true } } ] }' node_counter=$(((node_counter)%length +1)) done
也许它可以帮助别人,但是我也遇到了同样的问题,这是由于日志变得太大而导致的存储空间不足造成的。
希望它可以帮助别人! 🙂
我今天坚持与分配相同的问题。 W. Andrew Loe III在他的回答中提出的脚本对我来说不起作用,所以我修改了一下,最终奏效了:
#!/usr/bin/env bash # The script performs force relocation of all unassigned shards, # of all indices to a specified node (NODE variable) ES_HOST="<elasticsearch host>" NODE="<node name>" curl ${ES_HOST}:9200/_cat/shards > shards grep "UNASSIGNED" shards > unassigned_shards while read LINE; do IFS=" " read -r -a ARRAY <<< "$LINE" INDEX=${ARRAY[0]} SHARD=${ARRAY[1]} echo "Relocating:" echo "Index: ${INDEX}" echo "Shard: ${SHARD}" echo "To node: ${NODE}" curl -s -XPOST "${ES_HOST}:9200/_cluster/reroute" -d "{ \"commands\": [ { \"allocate\": { \"index\": \"${INDEX}\", \"shard\": ${SHARD}, \"node\": \"${NODE}\", \"allow_primary\": true } } ] }"; echo echo "------------------------------" done <unassigned_shards rm shards rm unassigned_shards exit 0
现在,我不是一个Bash大师,但脚本真的为我的情况。 请注意,您需要为“ES_HOST”和“NODE”variables指定适当的值。
在我的情况下,达到了硬盘空间的上限。
看这篇文章: https : //www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html
基本上,我跑了:
PUT /_cluster/settings { "transient": { "cluster.routing.allocation.disk.watermark.low": "90%", "cluster.routing.allocation.disk.watermark.high": "95%", "cluster.info.update.interval": "1m" } }
因此,如果使用了<90%的硬盘空间,将分配它,并且如果使用> 95%的硬盘空间,则将碎片移动到群集中的另一台机器; 并每隔1分钟检查一次。
我有同样的问题,但根本原因是版本号(两个节点(有问题)1.4.2和两个节点(好)1.4.4)的差异)。 第一个和第二个答案(将“index.routing.allocation.disable_allocation”设置为false并将“cluster.routing.allocation.enable”设置为“all”)不起作用。
然而,@Wilfred Hughes(使用transient设置“cluster.routing.allocation.enable”为“all”)的答案给了我一个错误,下面的语句:
[NO(目标节点版本[1.4.2]比源节点版本[1.4.4]旧]]]
在将旧节点更新到1.4.4后,这些节点开始与其他好节点重合。
我也遇到了这个问题,我find了一个简单的方法来解决它。
-
获取未分配的分片的索引
$ curl -XGET http://172.16.4.140:9200/_cat/shards
-
安装策展人工具,并用它来删除索引
$ curator --host 172.16.4.140 delete indices --older-than 1 \ --timestring '%Y.%m.%d' --time-unit days --prefix logstash
注意:在我的情况下,索引是2016-04-21的logstash
- 然后再检查碎片,所有未分配的碎片消失!
在我的情况下,当我创build一个新的索引时 ,默认的number_of_replicas被设置为1.我的集群中的节点数量只有一个,所以没有额外的节点来创build副本,所以健康变成了黄色。 所以当我用settings属性创build索引并将number_of_replicas设置为0.然后,它工作正常。 希望这可以帮助。
PUT /customer { "settings": { "number_of_replicas": 0 } }
我也遇到这种情况,最后修好了。
首先,我将描述我的情况。 我在ElasticSearch集群中有两个节点,他们可以find对方,但是当我创build一个索引设置为“number_of_replicas”:2 ,“number_of_shards”:5时,ES显示黄色信号,unassigned_shards为5。
发生这个问题的原因是number_of_replicas的值,当我用1来设置它的值的时候,一切正常。
在我的情况下,具有旧共享的旧节点正在join群集,因此我们不得不closures旧节点并删除具有未分配碎片的索引。
可能会帮助,但是当我尝试在embedded模式下运行ES时遇到了这个问题。 修复是为了确保Node有本地(true)设置。
未分配碎片的另一个可能的原因是您的集群运行Elasticsearch二进制文件的多个版本。
从较新版本到以前版本的分片复制将无法工作
这可能是未分配碎片的根本原因。
弹性文档 – 滚动升级过程
我遇到了完全相同的问题。 这可以通过在重新启动elasticsearch之前暂时将分片分配设置为false来防止,但是如果已分配的分片已经存在,则不能修复未分配的分片。
在我的情况下,这是由于数据节点上没有可用的磁盘空间。 未分配的碎片仍然在重新启动后的数据节点上,但是它们不被主服务器识别。
刚从磁盘清理1个节点就得到了复制过程。 这是一个相当缓慢的过程,因为所有的数据都必须从1个数据节点复制到另一个。
我尝试了上面的几个build议,不幸的是他们都没有工作。 我们在应用程序写入错误的较低环境中有一个“日志”索引。 它是一个单节点集群。 我解决这个问题的方法是检查节点的YMLconfiguration文件,并看到它仍然有默认设置“gateway.expected_nodes:2”。 这覆盖了我们所有的其他设置。 每当我们在这个节点上创build一个索引时,它会尝试将5个分片中的3个分散到幻像第2个节点。 这些因此将显示为未分配,并且它们不能被移动到第一个和唯一的节点。
解决scheme是编辑configuration,将设置“gateway.expected_nodes”更改为1,因此它将退出在群集中查找其未被发现的兄弟,并重新启动Elastic服务实例。 此外,我不得不删除索引,并创build一个新的。 创build索引之后,碎片全部出现在第一个节点上,没有任何未分配的节点。
# Set how many nodes are expected in this cluster. Once these N nodes # are up (and recover_after_nodes is met), begin recovery process immediately # (without waiting for recover_after_time to expire): # # gateway.expected_nodes: 2 gateway.expected_nodes: 1
我试图删除未分配的分片或手动分配给特定的数据节点。 它没有工作,因为未分配的碎片不断出现,健康状况一直“红”。 然后我注意到其中一个数据节点处于“重启”状态。 我减less了数据节点的数量,杀死了它。 问题不再是可重复的。