ElasticSearch悬挂索引的处理

2024-08-13 15:09:00 浏览数 (2)

Dangling Indices

Dangling indices(悬空索引)指数据存储在一个或多个节点磁盘上但当前集群的clusterMetaData中并不包含这些索引信息。

ES数据节点的启动会首次从dataPath路径下加载这些索引数据,然后master能够获取到这些索引数据。

Dangling indices通常是由以下几种情况产生的:

  1. 当有数据结点nodeA处于offline状态,而此时在集群中通过DELETE操作删除索引,删除的索引数大于集群设置的tombstones数量(默认为500),然后该数据节点NodeA启动并重新加入集群,DELETE操作将索引信息从clusterMetaData中删除,而索引的真实数据在nodeA磁盘中
  2. 可能是因为原始集群丢失了其所有主节点的原因,原始集群中的某个节点添加到另一个集群中。添加到另一个集群的节点,数据真实存储在节点中,但新集群的clusterMetaData中不包含这些索引数据的信息
  3. 对于集群的数据节点来说,可能是从备份中还原了老的、旧的索引文件
  4. 集群丢失了所有主节点,并且从备份中还原了这些主节点,但是备份中的主节点不包含这些索引信息,同样是节点存储着索引数据,但主节点维护的clusterMetaData中不包含这些索引信息

分析源码可知,ES对Dangling Indices的处理策略是首先会去寻找并判定数据节点中的哪些索引属于Dangling状态,然后组装好这些Indices,最后将这些Dangling Indices发送给master等待着后续的Allocation操作。上述的findNewDanglingIndices(…)函数主要职责就是寻找并判定处于Dangling状态的索引,可以看到当一个索引本身是Dangling Index,但在判定过程中发现clusterMetaData中已经存在与当前Dangling索引完全一样名称的索引时,则会报出WARN:can not be imported as a dangling index…;即尽管是Dangling indices,但因为存在与clusterMetaData中重名的缘故,因此ES自身不能像处理正常Dangling indices那样来处理此索引。ES会选择放弃这类Dangling indices的处理

对于这些重名的Dangling indices,查阅了一些资料,发现并没有比较好的方式来处理;ES官方讨论区推荐的方式为要么删除Dangling indices;要么是删除ES中已经存在的与Dangling状态同名的索引,别的也没有比较好的方式;

深想下这个问题,因为是clusterMetaData中存在重名的indices,所以才导致ES无法正确的处理Dangling indices。如果能对已存在ES集群中的索引名称进行rename,规避重名的情况,那ES就能够正确处理Dangling状态的indices了。于是Google了indices rename的操作,包括clone、reindex、snapshot等主要实现方式(暂不限于ES的版本),通过这些操作对重名的索引更改名称,然后ES就可以正常的处理Dangling indices了。

处理方法

下面是以8.11.3为例演示。

PS:从ES7.9开始才支持通过接口方式对dangling索引进行处理

列出https://www.elastic.co/guide/en/elasticsearch/reference/current/dangling-indices-list.html

删除https://www.elastic.co/guide/en/elasticsearch/reference/current/dangling-index-delete.html

导入https://www.elastic.co/guide/en/elasticsearch/reference/current/dangling-index-import.html

列出悬挂索引

代码语言:txt复制
shell写法
$ curl -s 127.0.0.1:9200/_dangling/ | jq .
{
  "_nodes": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "cluster_name": "docker-cluster",
  "dangling_indices": [
    {
      "index_name": "index1-2023.12.14",
      "index_uuid": "guCbNOLwQeWD08EomKI_OA",
      "creation_date_millis": 1702522905778,
      "node_ids": [
        "MLCJQzgmRzOHpHBIgDqD4Q"
      ]
    }
  ]
}


python版本写法:
from elasticsearch import Elasticsearch
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
def get_dangling_indices(es):
    response = es.transport.perform_request('GET', '/_dangling/')
    return response

dangling_indices = get_dangling_indices(es)['dangling_indices']
print(dangling_indices)

if dangling_indices:
    print("Dangling indices:")
    for index in dangling_indices['indices']:
        print(index)
else:
    print("No dangling indices found.")

删除

代码语言:txt复制
POST /_dangling/<index-uuid>?accept_data_loss=true

例如:
$ curl -s -XPOST -H Content-Type:"application/json" 127.0.0.1:9200/_dangling/guCbNOLwQeWD08EomKI_OA?accept_data_loss=true

导入

代码语言:txt复制
POST /_dangling/<index-uuid>?accept_data_loss=true

小结

总结下来,处理重名的Dangling indices的方式主要有如下三种:

  1. 删除存储在磁盘上的Dangling indices(一定的数据丢失)
  2. 删除已存储在ES中的重名索引(一定的数据丢失)
  3. 对已存储在ES中的索引进行rename操作,然后由ES正常处理Dangling indices(操作上繁琐一些)

其实最好的方式应该是尽可能的规避这个问题的发生,通过调研客户环境发现其ES集群非常不稳定,经常会出现节点卡死并带有重启的操作;所以对此处理的策略是依据处理的数据量做好ES集群的规划,包括master、data节点的部署划分、依据ES能力进行正常的写入与搜索等操作。尽可能减少或避免繁重的且会导致ES卡死的操作,进而避免ES节点频繁的重启发生。

参考:

https://searchkit.cn/article/15225

https://www.jianshu.com/p/bb2cfa6cdd8d

0 人点赞