ElasticSearch:未分配的碎片,如何解决?

Spa*_*nky 152 sharding master elasticsearch

我有一个包含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
Run Code Online (Sandbox Code Playgroud)

我不得不重新启动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
}
Run Code Online (Sandbox Code Playgroud)

现在我的群集处于黄色状态.解决此问题的最佳方法是什么?

  • 删除(取消)分片?
  • 将分片移动到另一个节点?
  • 将分片分配给节点?
  • 将'number_of_replicas'更新为2?
  • 还有别的吗?

有趣的是,当添加一个新索引时,该节点开始处理它并与群集的其余部分一起玩得很好,它只是留下未分配的分片.

关注问题:我是否做错了导致这种情况发生在一开始?对重新启动节点时以这种方式运行的集群,我没有多少信心.

注意:如果由于某种原因运行单个节点群集,则可能只需执行以下操作:

curl -XPUT 'localhost:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}'
Run Code Online (Sandbox Code Playgroud)

Wil*_*hes 109

默认情况下,Elasticsearch将动态地为节点重新分配分片.但是,如果您已禁用分片分配(可能是您进行了滚动重新启动并忘记重新启用它),则可以重新启用分片分配.

# 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"
    }
}'
Run Code Online (Sandbox Code Playgroud)

然后Elasticsearch将正常重新分配分片.这可能很慢,考虑提高indices.recovery.max_bytes_per_seccluster.routing.allocation.node_concurrent_recoveries加快速度.

如果您仍然遇到问题,可能还有其他问题,请查看Elasticsearch日志中的错误.如果您看到EsRejectedExecutionException您的线程池可能太小.

最后,您可以使用重新路由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
        }
    }]
}'
Run Code Online (Sandbox Code Playgroud)

  • 你需要添加`-H'Content-Type:application/json'`如果你得到错误`Content-Type header [application/x-www-form-urlencoded]不支持 (4认同)
  • 当我这样做时,我得到:`{"error":"ElasticsearchIllegalArgumentException [[allocate]无法在未分配的分片列表中找到[logstash-2015.01.05] [1]"","状态":400}`即使我可以看到碎片是ES-Head中未分配的碎片之一 (3认同)
  • 自版本 5.0 以来,“分配”命令[已更改以提供更多选项](https://www.elastic.co/guide/en/elasticsearch/reference/current/writing_50_allocation.html#_reroute_commands) - 上面的示例现在将为“allocate_empty_primary”,省略“allow_primary”参数。 (2认同)

Spa*_*nky 53

好的,我已经在ES支持的帮助下解决了这个问题.在所有节点(或您认为是导致问题的节点)上向API发出以下命令:

curl -XPUT 'localhost:9200/<index>/_settings' \
    -d '{"index.routing.allocation.disable_allocation": false}'
Run Code Online (Sandbox Code Playgroud)

<index>你认为哪个指数是罪魁祸首.如果您不知道,只需在所有节点上运行:

curl -XPUT 'localhost:9200/_settings' \
    -d '{"index.routing.allocation.disable_allocation": false}'
Run Code Online (Sandbox Code Playgroud)

我还将此行添加到我的yaml配置中,从那时起,服务器/服务的任何重新启动都没有问题.碎片立即重新分配回来.

FWIW,为了回答一个经常被追捧的问题,将MAX_HEAP_SIZE设置为30G,除非您的机器具有低于60G的RAM,在这种情况下将其设置为可用内存的一半.

参考

  • 请注意,路由分配是群集范围的设置,因此将命令发送到哪个节点无关紧要. (3认同)
  • 要在1.1.1版本中解决这个问题,我应该使用cluster.routing.allocation.enable = none吗? (2认同)
  • 那里不再记录分配禁用,至少从 11 月 20 日起是这样。 (2认同)
  • 在版本 6.8 中,我收到错误: `{ "type": "illegal_argument_exception", "reason": "unknown 设置 [index.routing.allocation.disable_allocation] 请检查是否安装了任何必需的插件,或检查重大更改文档以获取删除设置" } ],` (2认同)

W. *_*III 38

这个小小的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
Run Code Online (Sandbox Code Playgroud)

  • 该脚本抛出错误: `{"error":"Content-Type header [application/x-www-form-urlencoded] is not support","status":406}{"error":"Content-Type header [ application/x-www-form-urlencoded] 不受支持","status":406}` (3认同)

Edi*_*Edi 15

唯一对我有用的是更改number_of_replicas(我有2个副本,所以我将其更改为1然后再更改为2).

第一:

PUT /myindex/_settings
{
    "index" : {
        "number_of_replicas" : 1
     }
}
Run Code Online (Sandbox Code Playgroud)

然后:

PUT /myindex/_settings
{
    "index" : {
        "number_of_replicas" : 2
     }
}
Run Code Online (Sandbox Code Playgroud)

(我已经在这个问题上找到了答案)


Yog*_*war 12

我也遇到了类似的错误。这发生在我身上,因为我的一个数据节点已满,并且由于分片分配失败。如果存在未分配的分片,并且您的集群是 RED 并且很少有索引也是 RED,那么在这种情况下,我已按照以下步骤操作,并且这些操作非常有效。
在 kibana 开发工具中 -

GET _cluster/allocation/explain
Run Code Online (Sandbox Code Playgroud)

如果有任何未分配的分片,那么您将获得详细信息,否则将抛出 ERROR。

只需运行以下命令即可解决所有问题-

POST _cluster/reroute?retry_failed
Run Code Online (Sandbox Code Playgroud)

感谢 -
https://github.com/elastic/elasticsearch/issues/23199#issuecomment-280272888


Nis*_*mar 9

如果将以下配置设置为all,则Elasticsearch会自动分配分片.可以使用rest api以及 cluster.routing.allocation.enable:all设置此配置

如果即使在应用下面的配置后,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
Run Code Online (Sandbox Code Playgroud)


小智 6

我今天遇到了同样的分片分配问题.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
Run Code Online (Sandbox Code Playgroud)

现在,我不是一个Bash大师,但脚本真的适合我的情况.请注意,您需要为"ES_HOST"和"NODE"变量指定适当的值.

  • 为了使上面的脚本与ES5x一起使用,将`allocate`替换为`allocate_empty_primary`并将`\"allow_primary \":true`替换为`\"accept_data_loss \":true` (2认同)

Jua*_*che 5

也许它对某人有帮助,但我遇到了同样的问题,这是由于日志变得太大而导致存储空间不足。

希望它能帮助别人!:)


小智 5

在我的例子中,当我创建一个新索引时,默认的number_of_replicas设置为 1。我的集群中的节点数量只有一个,所以没有额外的节点来创建副本,所以健康状况变成了黄色。因此,当我使用settings属性创建索引并将number_of_replicas设置 为 0 时,它工作正常。希望这可以帮助。

PUT /customer
{
    "settings": {
        "number_of_replicas": 0
    }
}
Run Code Online (Sandbox Code Playgroud)


use*_*471 5

我也遇到了这个问题,我找到了一个简单的方法来解决它。

  • 获取未分配分片的索引

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
    Run Code Online (Sandbox Code Playgroud)
  • 安装curator Tools,并用它来删除索引

    $ curator --host 172.16.4.140 delete indices --older-than 1 \
           --timestring '%Y.%m.%d' --time-unit days --prefix logstash
    
    Run Code Online (Sandbox Code Playgroud)

    注意:在我的例子中,索引是当天的logstash 2016-04-21

  • 然后再次检查分片,所有未分配的分片都消失了!

  • @sim,非常感谢您对我的回答进行编辑。我编辑能力很差,以后会多加注意。 (2认同)

man*_*ays 5

就我而言,达到了硬盘空间上限.

看看这篇文章: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"
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果使用<90%的硬盘空间,它将分配,如果使用> 95%的硬盘空间,则将分片移动到群集中的另一台机器; 它每1分钟检查一次.