ElasticSearch:未分配的碎片,如何修复?
Posted
技术标签:
【中文标题】ElasticSearch:未分配的碎片,如何修复?【英文标题】:ElasticSearch: Unassigned Shards, how to fix? 【发布时间】:2013-11-26 20:41:55 【问题描述】:我有一个 4 个节点的 ES 集群:
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,当它回来时,它重新加入集群没有问题,但留下了 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
'
【问题讨论】:
【参考方案1】:ES 7.4.2 上的类似问题,命令已更改。正如答案中已经提到的,首先要检查GET _cluster/allocation/explain?pretty
,然后检查POST _cluster/reroute?retry_failed
主要
您必须通过 "accept_data_loss": true
获得主分片
POST _cluster/reroute
"commands": [
"allocate_stale_primary":
"index": "filebeat-7.4.2-xxxx",
"shard": 0,
"node": "my_node",
"accept_data_loss": false
]
副本
POST _cluster/reroute
"commands": [
"allocate_replica":
"index": "filebeat-7.4.2-xxxx",
"shard": 0,
"node": "my_other_node"
]
cluster-reroute doc
【讨论】:
【参考方案2】:如果您有未分配的分片,通常第一步是调用allocation explain API 并查找原因。根据原因,你会做一些事情。以下是我想到的一些:
节点没有足够的磁盘空间(检查disk-based allocation设置) 由于allocation is disabled 或allocation filtering 或awareness 等限制,节点无法分配分片(例如,节点位于集群的错误一侧,例如其他可用区或热节点或热节点) 加载分片时出错。例如。文件校验和失败,分析器引用的同义词文件丢失有时它有助于快速启动它,例如使用 Cluster Reroute API 手动分配分片,或者禁用和重新启用副本。
如果您需要有关操作 Elasticsearch 的更多信息,请查看 Sematext 的 Elasticsearch Operations training(免责声明:我正在提供)。
【讨论】:
【参考方案3】:首先使用cluster health API 获取集群的当前运行状况,其中红色表示缺少一个或多个主分片,黄色表示缺少一个或多个副本分片。
在此之后,使用cluster allocation explain API 了解为什么缺少特定分片并且 elasticsearch 无法在数据节点上分配它。
一旦找到确切的根本原因,请尝试解决问题,这通常需要更改一些集群设置(在@wilfred 回答earlier 中提到)但在某些情况下,如果它的副本分片,并且您有另一个副本如果有相同的分片(即另一个副本)可用,您可以使用update replica setting 减少副本数,然后在需要时再次增加它。
除此之外,如果您的集群分配 API 提到它没有有效的数据节点来分配分片,那么您需要添加新的数据节点,或者更改 shard allocation awareness settings。
【讨论】:
【参考方案4】:我也遇到了类似的错误。这发生在我身上,因为我的一个数据节点已满,并且由于分片分配失败。如果存在未分配的分片,并且您的集群是 RED,并且很少有索引也是 RED,那么在这种情况下,我已按照以下步骤操作,这些步骤就像冠军一样工作。 在 kibana 开发工具中-
GET _cluster/allocation/explain
如果有任何未分配的分片,那么您将获得详细信息,否则将抛出错误。
只需在命令下方运行即可解决所有问题-
POST _cluster/reroute?retry_failed
感谢 -https://github.com/elastic/elasticsearch/issues/23199#issuecomment-280272888
【讨论】:
非常感谢,帮我节省了很多时间。【参考方案5】:这也可能是磁盘空间的原因, 在 Elasticsearch 7.5.2 中,默认情况下,如果磁盘使用率高于 85%,则不会将副本分片分配给任何其他节点。
这可以通过设置不同的阈值或在 .yml 中或通过 Kibana 禁用它来解决
PUT _cluster/settings
"persistent":
"cluster.routing.allocation.disk.threshold_enabled": "false"
【讨论】:
【参考方案6】:在处理损坏的分片时,您可以将复制因子设置为 0,然后将其设置回原始值。这应该会清除大部分(如果不是全部)损坏的分片,并重新定位集群中的新副本。
将未分配副本的索引设置为使用复制因子 0:
curl -XGET http://localhost:9200/_cat/shards |\
grep UNASSIGNED | grep ' r ' |\
awk 'print $1' |\
xargs -I curl -XPUT http://localhost:9200//_settings -H "Content-Type: application/json" \
-d ' "index": "number_of_replicas": 0'
将它们设置回 1:
curl -XGET http://localhost:9200/_cat/shards |\
awk 'print $1' |\
xargs -I curl -XPUT http://localhost:9200//_settings -H "Content-Type: application/json" \
-d ' "index": "number_of_replicas": 1'
注意:如果您对不同的索引有不同的复制因子,请不要运行此命令。这会将所有索引的复制因子硬编码为 1。
【讨论】:
【参考方案7】:我只是先增加了
“index.number_of_replicas”
减 1(等到节点同步),然后再减 1,这有效地删除了未分配的分片,集群再次变为绿色,没有丢失任何数据的风险。
我相信有更好的方法,但这对我来说更容易。
希望这会有所帮助。
【讨论】:
【参考方案8】:我有两个索引,其中未分配的分片似乎无法自我修复。我最终通过临时添加一个额外的数据节点[1]解决了这个问题。在指数变得健康并且一切稳定为绿色后,我删除了额外的节点,系统能够(再次)重新平衡并进入健康状态。
最好避免一次杀死多个数据节点(这就是我进入这种状态的方式)。很可能,我没有为至少一个分片保留任何副本/副本。幸运的是,Kubernetes 保留了磁盘存储,并在我重新启动数据节点时重新使用它。
...已经过了一段时间...
好吧,这次只是添加一个节点似乎没有用(在等待了几分钟之后),所以我开始在 REST API 中四处寻找。
GET /_cluster/allocation/explain
这显示了我的新节点"decision": "YES"
。
顺便说一句,由于"the node is above the low watermark cluster setting"
,所有预先存在的节点都有"decision": "NO"
。所以这可能与我之前提到的情况不同。
然后我做了以下简单的 POST[2]没有正文,让事情进展顺利...
POST /_cluster/reroute
其他说明:
非常有帮助:https://datadoghq.com/blog/elasticsearch-unassigned-shards
其他可能有效的方法。将cluster_concurrent_rebalance
设置为0
,然后设置为null
——正如我演示的here。
[1]如果你有足够的空间,在 Kubernetes 中很容易做到:只需通过仪表板扩展有状态集。
[2] 使用 Kibana 的“开发工具”界面,我不必费心使用 SSH/exec shell。
【讨论】:
【参考方案9】:好的,我在 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'
我还将这一行添加到我的 yaml 配置中,从那时起,服务器/服务的任何重新启动都没有问题。分片立即重新分配回来。
FWIW,要回答一个经常受到追捧的问题,请将 MAX_HEAP_SIZE 设置为 30G,除非您的计算机的 RAM 小于 60G,在这种情况下,请将其设置为可用内存的一半。
参考文献
Shard Allocation Awareness【讨论】:
要在 1.1.1 版本中解决这个问题,我应该使用 cluster.routing.allocation.enable = none 吗? 那里不再记录分配禁用,至少截至 11 月 20 日没有。 请注意,路由分配是集群范围的设置,因此您将命令发送到哪个节点并不重要。 我在我的 es yml 文件中添加了两者。index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: none
但是仍然显示未分配的分片.. 可能是什么原因?
在 6.8 版中出现错误: "type": "illegal_argument_exception", "reason": "unknown setting [index.routing.allocation.disable_allocation] please check that any required plugins are installed, or check the breaking changes documentation for removed settings" ],
【参考方案10】:
对我来说,这是通过从开发控制台运行以下命令解决的:“POST /_cluster/reroute?retry_failed”
.....
我首先查看索引列表,看看哪些索引是红色的,然后运行
"get /_cat/shards?h=[INDEXNAME],shard,prirep,state,unassigned.reason"
并看到它的分片卡在 ALLOCATION_FAILED 状态,因此运行上面的重试导致它们重新尝试分配。
【讨论】:
从 5.6.3 版开始,命令应该是 get /_cat/shards/[INDEXNAME]?h=,shard,prirep,state,unassigned.reason【参考方案11】:如果以下配置设置为 all,Elasticsearch 会自动分配分片。可以使用rest api as well 设置此配置 cluster.routing.allocation.enable: 全部
如果即使在应用以下配置后,es 无法自动分配分片,那么您必须自己强制分配分片。 ES official link for this
我编写了一个脚本来强制跨集群分配所有未分配的分片。
下面的数组包含您想要平衡未分配分片的节点列表
#!/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
【讨论】:
这个脚本不起作用,也就是说,我运行它之后,我仍然有未分配的碎片。 @ChrisF 在 line1 中:您需要将 node1、node2、node3 替换为实际的节点名称。您可以使用 curl localhost:9200/_cat/nodes 获取它们。【参考方案12】:我尝试删除未分配的分片或手动将它们分配给特定的数据节点。它不起作用,因为未分配的碎片不断出现,并且健康状态一遍又一遍地“红色”。 然后我注意到其中一个数据节点卡在“重新启动”状态。我减少了数据节点的数量,杀死了它。问题不再重现。
【讨论】:
【参考方案13】:就我而言,已达到硬盘空间上限。
看这篇文章: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"
如果使用 95%的硬盘空间,则将分片移动到集群中的另一台机器;它每 1 分钟检查一次。
【讨论】:
【参考方案14】:我也遇到这种情况,终于解决了。
首先,我将描述我的情况。我在 ElasticSearch 集群中有两个节点,它们可以相互找到,但是当我使用设置 "number_of_replicas" : 2、"number_of_shards" : 5 创建索引时,ES 显示黄色信号并且 unassigned_shards 为 5。
出现问题是因为number_of_replicas的值,当我将其值设置为1时,一切正常。
【讨论】:
副本数应始终为您拥有的节点数的 N-1。因此,在您有 2 个节点的场景中,其中 1 个节点包含主分片,而另一个节点具有副本,因此您的副本数应设置为 1。N = 2,N - 1 = 1。【参考方案15】:在我的例子中,当我创建一个新的 index 时,默认的 number_of_replicas 设置为 1。而且我的集群中的节点数只有一个,所以没有额外的节点来创建副本,所以运行状况变成了黄色。 因此,当我使用 settings 属性创建索引并将 number_of_replicas 设置为 0 时,它工作正常。希望这会有所帮助。
PUT /customer
"settings":
"number_of_replicas": 0
【讨论】:
【参考方案16】:我也遇到了这个问题,我找到了一个简单的方法来解决它。
获取未分配分片的索引
$ curl -XGET http://172.16.4.140:9200/_cat/shards
安装curator Tools,并用它来删除索引
$ curator --host 172.16.4.140 delete indices --older-than 1 \
--timestring '%Y.%m.%d' --time-unit days --prefix logstash
注意:就我而言,索引是 2016 年 4 月 21 日当天的 logstash
然后再次检查分片,所有未分配的分片都消失了!【讨论】:
@sim,非常感谢您对我的回答进行编辑。我编辑很差,以后会多注意的。 对我来说是:curator_cli --host 127.0.0.1 delete_indices --filter_list '["filtertype":"pattern","kind":"prefix","value":"logstash-"]'
【参考方案17】:
我尝试了上面的几个建议,但不幸的是,它们都没有奏效。在应用程序写入错误的较低环境中,我们有一个“日志”索引。它是一个单节点集群。为我解决的问题是检查节点的 YML 配置文件,并看到它仍然具有默认设置“gateway.expected_nodes:2”。这覆盖了我们拥有的任何其他设置。每当我们在这个节点上创建一个索引时,它会尝试将 5 个分片中的 3 个分散到虚拟的第二个节点。因此,这些将显示为未分配,并且永远无法移动到第一个也是唯一的节点。
解决方案是编辑配置,将设置“gateway.expected_nodes”更改为 1,这样它就不会在集群中寻找它永远找不到的兄弟,并重新启动 Elastic 服务实例。此外,我不得不删除索引,并创建一个新的。创建索引后,分片都出现在第一个也是唯一的节点上,没有一个是未分配的。
# 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
【讨论】:
【参考方案18】:我今天遇到了同样的分片分配问题。那个脚本 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”变量指定适当的值。
【讨论】:
不幸的是 ES5x 破坏了兼容性:elastic.co/guide/en/elasticsearch/reference/5.1/… 为了使上面的脚本能够与 ES5x 一起使用,请将allocate
替换为 allocate_empty_primary
并将 \"allow_primary\": true
替换为 \"accept_data_loss\": true
即使在应用了 Fawix 的建议后也得到"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406
【参考方案19】:
默认情况下,Elasticsearch 会动态地将分片重新分配给节点。但是,如果您禁用了分片分配(也许您执行了 rolling restart 并忘记重新启用它),您可以重新启用分片分配。
# 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
你的线程池may be too small。
最后,您可以使用reroute API 将分片显式重新分配给节点。
# 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
]
'
【讨论】:
当我这样做时,我得到了: "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400
尽管我可以看到分片是 ES-Head 中未分配的分片之一
顺便说一下,其他分片确实可以工作,但被列为未分配,然后其余分片自行修复。
这是个好建议。
自 5.0 版以来,“分配”命令 has changed to provide more options - 上面的示例现在是“allocate_empty_primary”,省略了“allow_primary”参数。
如果遇到错误Content-Type header [application/x-www-form-urlencoded] is not supported
,需要添加-H 'Content-Type: application/json'
【参考方案20】:
我遇到了完全相同的问题。这可以通过在重新启动 elasticsearch 之前将分片分配临时设置为 false 来防止,但是如果它们已经存在,这不会修复未分配的分片。
在我的情况下,这是由于数据节点上的可用磁盘空间不足造成的。重新启动后未分配的分片仍在数据节点上,但主节点无法识别它们。
只需从磁盘中清理 1 个节点,我就开始了复制过程。这是一个相当缓慢的过程,因为所有数据都必须从一个数据节点复制到另一个数据节点。
【讨论】:
【参考方案21】:未分配分片的另一个可能原因是您的集群运行了多个版本的 Elasticsearch 二进制文件。
从较新版本到前一个版本的分片复制 版本将不起作用
这可能是未分配分片的根本原因。
Elastic Documentation - Rolling Upgrade Process
【讨论】:
【参考方案22】:在我的例子中,一个具有旧共享的旧节点正在加入集群,因此我们必须关闭旧节点并删除具有未分配分片的索引。
【讨论】:
【参考方案23】:可能会有所帮助,但我在尝试以嵌入式模式运行 ES 时遇到了这个问题。修复是确保节点设置了 local(true)。
【讨论】:
【参考方案24】:唯一对我有用的是更改 number_of_replicas(我有 2 个副本,所以我将其更改为 1,然后再更改回 2)。
第一:
PUT /myindex/_settings
"index" :
"number_of_replicas" : 1
然后:
PUT /myindex/_settings
"index" :
"number_of_replicas" : 2
(我已经在this question回复了)
【讨论】:
这似乎会给网络和数据密集型集群的处理带来沉重的负担。你在大数据系统上试过吗?你能分享一下粗略的数字吗?【参考方案25】:也许它对某人有帮助,但我遇到了同样的问题,这是由于日志太大而导致存储空间不足。
希望它可以帮助某人! :)
【讨论】:
【参考方案26】:我遇到了同样的问题,但根本原因是版本号不同(两个节点上的 1.4.2(有问题)和两个节点上的 1.4.4(正常))。第一个和第二个答案(将“index.routing.allocation.disable_allocation”设置为 false 并将“cluster.routing.allocation.enable”设置为“all”)不起作用。
但是,@Wilfred Hughes 的回答(使用瞬态将“cluster.routing.allocation.enable”设置为“all”)给了我以下语句的错误:
[NO(目标节点版本 [1.4.2] 比源节点版本旧 [1.4.4])]
将旧节点更新到 1.4.4 后,这些节点开始与其他好的节点重新连接。
【讨论】:
【参考方案27】:这个小 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
【讨论】:
工作就像一个魅力。谢谢! 我收到了这个错误: "error":"JsonParseException[Unexpected character (',' (code 44)): 期望一个有效值(数字、字符串、数组、对象、 'true' , 'false' 或 'null')\n 在 [Source: [B@3b1fadfb; line: 6, column: 27]]","status": 500 我应该怎么做才能修复它 非常感谢!它节省了宝贵的时间! 脚本抛出错误:"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406
谢谢!为我工作(ElasticSearch 1.4.x)。以上是关于ElasticSearch:未分配的碎片,如何修复?的主要内容,如果未能解决你的问题,请参考以下文章