首页 文章

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

提问于
浏览
135

我有一个包含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?

  • 还有其他什么吗?

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

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

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

curl -XPUT 'localhost:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}'

19 回答

  • 5

    我尝试删除未分配的分片或手动将它们分配给特定的数据节点 . 它没有用,因为未分配的碎片不断出现, Health 状况一遍又一遍“红” . 然后我注意到其中一个数据节点处于“重启”状态 . 我减少了数据节点的数量,杀了它 . 问题不再可再生 .

  • 36

    未分配分片的另一个可能原因是您的群集正在运行Elasticsearch二进制文件的多个版本 .

    从较新版本到先前版本的分片复制将不起作用

    这可能是未分配的分片的根本原因 .

    Elastic Documentation - Rolling Upgrade Process

  • 12

    默认情况下,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_seccluster.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
            }
        }]
    }'
    
  • 6

    好的,我已经在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,除非您的机器具有低于60G的RAM,在这种情况下将其设置为可用内存的一半 .

    参考文献

  • 0

    这个小小的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
    
  • 1

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

    第一:

    PUT /myindex/_settings
    {
        "index" : {
            "number_of_replicas" : 1
         }
    }
    

    然后:

    PUT /myindex/_settings
    {
        "index" : {
            "number_of_replicas" : 2
         }
    }
    

    (我已经在this question找到了答案)

  • 0

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

    如果即使在应用下面的配置后,es也无法自动分配分片,那么你必须自己强制分配分片 . ES official link for this

    我编写了一个脚本来强制在集群中分配所有未分配的分片 .

    下面的数组包含要在其中 balancer 未分配的分片的节点列表

    #!/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
    
  • 9

    我遇到了完全相同的问题 . 这可以通过在重新启动elasticsearch之前临时将分片分配设置为false来防止,但如果它们已经存在,则不会修复未分配的分片 .

    在我的情况下,这是由数据节点上缺少可用磁盘空间引起的 . 未分配的分片,在重新启动后仍在数据节点上,但主分机无法识别 .

    只需清理磁盘中的1个节点就可以开始复制过程了 . 这是一个相当慢的过程,因为所有数据都必须从1个数据节点复制到另一个数据节点 .

  • 4

    我今天遇到了同样的分片分配问题 . 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”变量指定适当的值 .

  • 1

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

    看看这篇文章: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分钟检查一次 .

  • 48

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

    希望它可以帮到某人! :)

  • 3

    我有同样的问题,但根本原因是版本号的差异(两个节点上的1.4.2(有问题)和两个节点上的1.4.4(ok)) . 第一个和第二个答案(将“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这些节点开始与其他好节点重新绑定 .

  • 2

    我也遇到了这个问题,我找到了解决问题的简单方法 .

    • 获取未分配的分片的索引
    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
    • 安装curator工具,并用它来删除索引
    $ curator --host 172.16.4.140 delete indices --older-than 1 \
           --timestring '%Y.%m.%d' --time-unit days --prefix logstash
    

    NOTE: 在我的情况下,索引是2016-04-21当天的logstash

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

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

    PUT /customer
    {
        "settings": {
            "number_of_replicas": 0
        }
    }
    
  • 1

    我也遇到了这种情况,最后修好了 .

    首先,我将描述我的情况 . 我在ElasticSearch集群中有两个节点,它们可以互相找到,但是当我创建一个设置为 "number_of_replicas" : 2 ,"number_of_shards":5的索引时,ES显示黄色信号,unassigned_shards为5 .

    出现问题是因为 number_of_replicas 的值,当我用 1 设置它的值时,一切都很好 .

  • 0

    在我的情况下,具有旧共享的旧节点正在加入群集,因此我们必须关闭旧节点并使用未分配的分片删除索引 .

  • 0

    我尝试了上面的一些建议,不幸的是没有一个有效 . 我们在较低的环境中有一个“日志”索引,应用程序会在其中编写错误 . 它是单节点集群 . 为我解决的是检查节点的YML配置文件,并发现它仍然具有默认设置“gateway.expected_nodes:2” . 这超越了我们拥有的任何其他设置 . 每当我们在这个节点上创建索引时,它会尝试将3个分片中的3个分散到虚拟第2个节点 . 因此,它们将显示为未分配,并且永远不会移动到第1个且唯一的节点 .

    解决方案是编辑配置,将设置“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
    
  • 3

    对我来说,通过从开发控制台运行它来解决这个问题:“POST / _cluster / reroute?retry_failed”

    .....

    我首先查看索引列表,看看哪些索引是红色然后运行

    “得到/_cat/shards?h=[INDEXNAME],shard,prirep,state,unassigned.reason”

    并且看到它的分片卡在ALLOCATION_FAILED状态,因此运行上面的重试会导致它们重新尝试分配 .

  • 103

    可能有帮助,但在尝试以嵌入模式运行ES时遇到了这个问题 . 修复是为了确保Node具有本地(true)设置 .

相关问题