天天看点

ES 的 unassigned shards 核心处理方案

背景:管理过数百个集群,使用方式千变万化,出现过各种各样的shards分配不了的情况,趁此假期做一些unassigned处理方案的总结;

先总结一下:所有的unassigned都可以通过explain API查到原因和处理方案

GET /_cluster/allocation/explain
{
  "index":"index_name",
  "shard":0,
  "primary":false
}
           

先找到所有的unassigned分片:

curl -XGET localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED
           

出现unassigned的主要原因:

  • nodes 数小于分片副本数
  • 节点失联(node_left)
  • node_permission设置不合理
  • rebalance过程中的yellow(一般不需要处理,只需要查清楚rebalance的原因)
  • 磁盘空间不足(空间不足只能扩容或者删除旧的index,下面不做详细介绍)
  • 节点暂时出现问题,等几分钟后又好了,这时候retry 5 次已经结束了,unassigned的分片已经不能分配了(此时可以通过retry API 进行重试,概率较小,直接贴出解决方案,下面不详细介绍了)

数据不重要可以delete:

如果数据不重要,可以直接delete index;

或者将副本数设置为0,再设置回原配置(yellow的情况)

修改副本分片API:

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


删除index API:

delete index_name
           

设置不合理处理方案:

1.node数小于副本分片数

直接修改副本分片数API:

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

如果发现是有某些节点被exclude导致节点不够,在确认node正常后,可以将exclude去掉:

PUT _cluster/settings
{
  "transient" : {
    "cluster.routing.allocation.exclude._ip" : null
  }
}
           

2.设置索引在节点上最多容纳的分片不合理:

可增大这个参数:

PUT /index_name/_settings
{
  "index.routing.allocation.total_shards_per_node":"3"
}
           

这个参数设置不合理可能会造成如下bug:

ES 的 unassigned shards 核心处理方案

暂时没有正常的解决方案:retry也不会生效,只能改大total_shards_per_node参数,原因是es的allocation是通过分配器和17个决策器(责任链模式)进行分配的,只要节点符合决策条件就会分配,如上图的情况,只要前五个节点符合所有决策器条件就会直接分配,等轮到第6个shard开始分配的时候,发现不符合条件了,前五个shard也不会去重新分配,就只能让第6个shard变成unassigned状态了;

补充retry API:防止修改配置不生效

POST /_cluster/reroute?retry_failed=true
           

如果由于故障(异常)导致的分配不了的解决方案:

1.首先是解决故障,比如看到日志发现是分词器找不到导致不能正常运行,那么首先将分词器装好,然后再解决unassigned的问题,正常情况ES会自动分配,但是由于出现故障,导致分配分片的5次(默认)重试机会用完了,所以不会再自动分配,所以需要在故障解决完成之后进行retry;

POST /_cluster/reroute?retry_failed=true
           

处理节点离开集群后主分片不能分配的问题

节点离开再回来这种问题不是很好处理,可能性很多,一般的解决方案如下:

1.尝试进行retry

POST /_cluster/reroute?retry_failed=true
           

2.如果是自己操作的,设置延迟allocation时间较大,则不需要处理,等待allocation副本分配即可,或者减小延迟时间

(注:延迟分配是为了防止节点掉出去后立刻进行副本分片分配,比如node1掉出去了,shard马上开始重新分配,30s后node1又回来了,于是发现node1上的shard无效了,于是干掉node1上的shard,然后又重新分配一次,这样大大的消耗了性能)

修改延迟分配的时间API:

PUT  */_settings
{
    "settings": {
      "index": {
        "unassigned": {
          "node_left": {
            "delayed_timeout": "1m"
          }
        }
      }
    }
  }
           

3.手动分配分片

如果到了需要手动分配这一步,说明故障时间比较长,或者故障节点过多,如果是red,那么这时候数据丢失已经无法避免了;

red情况下手动分配主分配操作流程:

1.先查询未分配的主分片原来是在哪个节点上

GET /order_orderlist/_shard_stores

2.将主分片分配(只丢失部分数据)

POST _cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "index_name",
        "shard": 4,
        "node": "node1",
        "accept_data_loss" : true
      }
    }
  ]
}

3.如果数据不重要,可以不用放到原来的节点上,直接新建一个空分片替代

POST _cluster/reroute
{
  "commands": [
    {
      "allocate_empty_primary": {
        "index": "test_11",
        "shard": 2,
        "node": "node0",
        "accept_data_loss" : true
      }
    }
  ]
}

           

yellow情况下手动分配副本分片操作:

POST /_cluster/reroute
{ 
  "commands" :[
    { 
      "allocate_replica" : 
         { 
           "index" : "index_name", 
           "shard" : 0, 
           "node": "node1"
         }
      }
   ]
 }
           

补充:不是所有的unassigned都是不正常的,集群启动、扩容的时候就会有短暂的yellow,甚至Shard allocation过程由于延迟机制的设置,也会出现正常的yellow情况(当然这种也是不正常的,只是不是shard的不正常,而是集群层面的不正常,比如压力过大等情况)

继续阅读