当前位置:   article > 正文

ES5.6.4源码解析----分片在磁盘间的分配策略_索引分片的源码分析

索引分片的源码分析

引文

ES的索引是由若干个分片组成,在索引创建的时候需要指定分片个数、副本个数。如果没有指定,分片个数默认为5个,副本个数默认1个。一个索引的各个分片会根据路由算法均匀的分布于各个节点中。本文提出的问题是,如果一个分片指定分片到某个节点,而该节点的数据路径分布于多个磁盘上,即elasticsearch.yml中的配置如下:

path.data:/disk1/data/elasticsearch,/disk2/data/elasticsearch,/disk3/data/elasticsearch
  • 1

在ES为分片选择路径的时候,是如何选择将分片落地在哪个路径的呢?

何时分配分片

ES分片会在两种情况下去分配分片:

  • 创建索引
  • 分片被重新指派

无论是什么引起分片的分配,都需要调用如下的分片路径选择方法:

public static ShardPath selectNewPathForShard(NodeEnvironment env, ShardId shardId, IndexSettings indexSettings,
                                                  long avgShardSizeInBytes, Map<Path,Integer> dataPathToShardCount) throws IOException {

        final Path dataPath;
        final Path statePath;

        if (indexSettings.hasCustomDataPath()) {
            dataPath = env.resolveCustomLocation(indexSettings, shardId);
            statePath = env.nodePaths()[0].resolve(shardId);
        } else {
            BigInteger totFreeSpace = BigInteger.ZERO;
            for (NodeEnvironment.NodePath nodePath : env.nodePaths()) {
                totFreeSpace = totFreeSpace.add(BigInteger.valueOf(nodePath.fileStore.getUsableSpace()));
            }

            // TODO: this is a hack!!  We should instead keep track of incoming (relocated) shards since we know
            // how large they will be once they're done copying, instead of a silly guess for such cases:

            // Very rough heuristic of how much disk space we expect the shard will use over its lifetime, the max of current average
            // shard size across the cluster and 5% of the total available free space on this node:
            BigInteger estShardSizeInBytes = BigInteger.valueOf(avgShardSizeInBytes).max(totFreeSpace.divide(BigInteger.valueOf(20)));

            // TODO - do we need something more extensible? Yet, this does the job for now...
            final NodeEnvironment.NodePath[] paths = env.nodePaths();
            NodeEnvironment.NodePath bestPath = null;
            BigInteger maxUsableBytes = BigInteger.valueOf(Long.MIN_VALUE);
            for (NodeEnvironment.NodePath nodePath : paths) {
                FileStore fileStore = nodePath.fileStore;

                BigInteger usableBytes = BigInteger.valueOf(fileStore.getUsableSpace());
                assert usableBytes.compareTo(BigInteger.ZERO) >= 0;

                // Deduct estimated reserved bytes from usable space:
                Integer count = dataPathToShardCount.get(nodePath.path);
                if (count != null) {
                    usableBytes = usableBytes.subtract(estShardSizeInBytes.multiply(BigInteger.valueOf(count)));
                }
                if (bestPath == null || usableBytes.compareTo(maxUsableBytes) > 0) {
                    maxUsableBytes = usableBytes;
                    bestPath = nodePath;
                }
            }

            statePath = bestPath.resolve(shardId);
            dataPath = statePath;
        }
        return new ShardPath(indexSettings.hasCustomDataPath(), dataPath, statePath, shardId);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

分配策略分析

下面根据上一小节的代码进行分析

1、预估分片的大小

1、获取该索引下已有分片的平均大小
2、计算path.data指定的数据路径的所有可用的空间的小的5%

取1,2中较大的值作为预估分片大小estShardSizeInBytes

2、 计算各个路径该索引的分片数
3、用公式计算各个路径的剩余可用空间大小
usableBytes = usableBytes-路径下该索引的分片数*estShardSizeInBytes
  • 1
4、选取最大

比较各个路径的usableBytes 值,最大的路径将拥有该分片。

总结

由于ES预估分片大小的算法并不准确,因此ES的分片分配策略并无法保证多个磁盘间的数据均衡分布。

举个例子:

假设数据路径,已经他们的剩余空间,总空间大小如下
/disk1/data/elasticsearch 10G 20G
/disk2/data/elasticsearch 9.5G 20G
/disk3/data/elasticsearch 9.5G 20G

先后创建2个索引people1,people2。他们的分片数都是1。
首先创建people1,根据上述算法,其分片的预估值为(10+9.5+9.5)*5% = 1.45G

由于该索引还没有分片,因此各个路径计算所得的剩余可用空间如下:
/disk1/data/elasticsearch 10G
/disk2/data/elasticsearch 9.5G
/disk3/data/elasticsearch 9.5G

/disk1/data/elasticsearch 剩余空间最多,people1唯一的分片分配给/disk1/data/elasticsearch。由于people1索引的数据为空,不影响/disk1/data/elasticsearch的剩余空间。因此people1创建后的剩余空间如下

/disk1/data/elasticsearch 10G 20G
/disk2/data/elasticsearch 9.5G 20G
/disk3/data/elasticsearch 9.5G 20G

按照people1的流程,可知people2的分片也是分片给/disk1/data/elasticsearch。因此两个索引的数据都将存放于该路径下。这样的结果就是导致两个索引的数据导入之后,造成磁盘间的数据倾斜问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/842289
推荐阅读
相关标签
  

闽ICP备14008679号