Elasticsearch Dangling Indices知识

2020-10-21  本文已影响0人  汤尼房
背景

前段时间客户根据看到的ES日志报了索引无法创建的Bug,研发工作完成差不多后,开始梳理前线客户Bug,调研后才发现原来是Dangling索引的问题;这篇文档算是对Dangling Indices知识的简短梳理。ES(5.6.4)日志的记录如下:

[2020-09-17T01:51:05,715][WARN ][o.e.g.DanglingIndicesState] [elasticsearch1] [[filebeat-2020.08.11/Uwim4o6nREed8_It7vBQ7A]] can not be imported as a dangling index, as index with same name already exists in cluster metadata

上述WARN信息,来源于ES的DanglingIndicesState类的findNewDanglingIndices(...)方法,如下:

/**
 * Finds new dangling indices by iterating over the indices and trying to find indices
 * that have state on disk, but are not part of the provided meta data, or not detected
 * as dangled already.
 */
Map<Index, IndexMetaData> findNewDanglingIndices(final MetaData metaData) {
    final Set<String> excludeIndexPathIds = new HashSet<>(metaData.indices().size() + danglingIndices.size());
    for (ObjectCursor<IndexMetaData> cursor : metaData.indices().values()) {
        excludeIndexPathIds.add(cursor.value.getIndex().getUUID());
    }
    excludeIndexPathIds.addAll(danglingIndices.keySet().stream().map(Index::getUUID).collect(Collectors.toList()));
    try {
        final List<IndexMetaData> indexMetaDataList = metaStateService.loadIndicesStates(excludeIndexPathIds::contains);
        Map<Index, IndexMetaData> newIndices = new HashMap<>(indexMetaDataList.size());
        final IndexGraveyard graveyard = metaData.indexGraveyard();
        for (IndexMetaData indexMetaData : indexMetaDataList) {
            if (metaData.hasIndex(indexMetaData.getIndex().getName())) {
                logger.warn("[{}] can not be imported as a dangling index, as index with same name already exists in cluster metadata",
                    indexMetaData.getIndex());
            } else if (graveyard.containsIndex(indexMetaData.getIndex())) {
                logger.warn("[{}] can not be imported as a dangling index, as an index with the same name and UUID exist in the " +
                    "index tombstones.  This situation is likely caused by copying over the data directory for an index " +
                    "that was previously deleted.", indexMetaData.getIndex());
            } else {
                logger.info("[{}] dangling index exists on local file system, but not in cluster metadata, " +
                    "auto import to cluster state", indexMetaData.getIndex());
                newIndices.put(indexMetaData.getIndex(), indexMetaData);
            }
        }
        return newIndices;
    } catch (IOException e) {
        logger.warn("failed to list dangling indices", e);
        return emptyMap();
    }
}

从WARN信息中可以得到两点信息:

结合ES集群重现上述问题的操作步骤:

Dangling Indices

Dangling indices(悬空索引)指数据存储在一个或多个节点磁盘上但当前集群的clusterMetaData中并不包含这些索引信息。ES数据节点的启动会首次从dataPath路径下加载这些索引数据,然后master能够获取到这些索引数据。Dangling indices通常是由以下几种情况产生的:

分析源码可知,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了。
小结

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

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

上一篇下一篇

猜你喜欢

热点阅读