通过_shrink API快速减少主分片数

在Elasticsearch集群中创建索引时,如果您无法评估实际数据量,可能导致设置的主分数很大,但实际业务的数据量并不多,此时您需要减少主分片数,防止因主分片数太多导致集群资源消耗过大或影响查询写入速率等。本文为您介绍如何通过_shrink API快速减少主分片数。

背景信息

使用Elasticsearch需要密切关注集群分片总数及索引分片数设置。集群分片总数越多,对应分片会占用大量的文件句柄耗用大量的集群资源。同样,索引分片数设置不合理,会对查询和写入均造成潜在的影响。

在创建索引时,如果您无法评估实际数据量,可能导致设置的索引主分数很大,但实际业务数据量并不多。通过reindex减少主分片数耗时太久,elastic提供了_shrink API可快速减少索引主分片数。shrink操作不会在原索引上直接缩小分片,基本流程如下:

  1. 创建一个和原索引配置相同的新索引,新索引主分片比原索引少,所有分片需汇集在一个节点,该节点预留的磁盘空间需要大于原索引主分片上的数据大小。

  2. 从原索引到新索引创建segments硬链接。

  3. 对新索引执行恢复操作,类似关闭的索引执行打开操作。

reindex与_shrink API的性能测试信息如下:

  • 测试环境:

    • 数据节点:数量为5个,规格为8核16 GB。

    • 索引数据:数据量为182 GB。

    • 分片数:原主分片数为30,目标分片数为5,副本数为0。

  • 测试结果

    方式

    耗时

    资源占用

    reindex

    3小时22分钟

    集群中有大量的写QPS,索引所占节点资源高。

    _shrink API

    15分钟

    shrink节点计算资源较高。

前提条件

  • Elasticsearch集群状态健康,且负载处于正常水位。

  • 根据集群数据节点个数、集群磁盘容量等因素,合理评估索引可减少的分片数。详细信息请参见评估Shard

  • 原索引必须处于green状态。

  • 原索引的文档总数不能超过2,147,483,519。

  • Elasticsearch集群中没有新索引的同名索引。

操作步骤

  1. 登录目标阿里云Elasticsearch实例的Kibana控制台,根据页面提示进入Kibana主页。
    登录Kibana控制台的具体操作,请参见登录Kibana控制台
    说明 本文以阿里云Elasticsearch 7.10.0版本为例,其他版本操作可能略有差别,请以实际界面为准。
  2. 单击右上角的Dev tools
  3. Console中,执行如下命令,将原索引设置为禁止写状态,副本置为0,且将分片汇集到集群中的一个节点上。

    以下示例以原索引shrink5为例,使用时需要替换为您的业务索引名。

    PUT shrink5/_settings
    {
        "index.routing.allocation.require._name": "es-cn-zvp25yhyy000y****-1ab7****-0001",
        "index.blocks.write": true,
        "index.number_of_replicas": 0
    }
                            

    参数

    说明

    index.routing.allocation.require._name

    设置分片汇集的目标节点name。节点name可通过GET _cat/nodes?v命令获取。

    说明

    在通过_shrink API减少主分片数之前,原索引的每个分片必须汇集到集群中的一个节点上。

    index.blocks.write

    是否禁用对索引的写操作,必须为true,即禁止写操作。

    说明

    在通过_shrink API减少主分片数之前,必须设置原索引为禁止写状态。

    index.number_of_replicas

    索引的副本分片数。

  4. 通过_shrink API减少主分片数。

    以下示例以将原索引shrink5的主分片数从30减少到5,并生成新索引shrink_hk5e_cn。使用时请替换索引名。

    POST shrink5/_shrink/shrink_hk5e_cn
    {
      "settings": {
        "index.blocks.write": null,
        "index.number_of_shards": 5,
        "index.number_of_replicas": 0,
        "index.routing.allocation.require._name": null
      }
    }

    参数

    说明

    index.blocks.write

    是否禁用对索引的写操作。在通过_shrink API减少主分片数后,需要将新索引的index.blocks.write置为null,即清除从原索引复制的配置。

    index.number_of_shards

    新索引的主分片数。

    重要
    • 触发shrink后,shrink_node节点CPU使用率和load_1m将比较高,建议在业务低峰期操作。

    • 原索引的主分片数一定要大于新索引,新索引的主分片数必须可被原索引的主分片数整除。例如,原索引的主分片数为8,则可以减少到4、2、1;原索引的主分片数为15,则可以减少到5、3、1。如果原索引的主分片数是质数,则只能减少到1。

    index.number_of_replicas

    新索引的副本分片数。

    index.routing.allocation.require._name

    设置将分片汇集的目标节点。在通过_shrink API减少主分片数后,需要将新索引的index.routing.allocation.require._name置为null清除从原索引复制的配置,或者删除原索引。

  5. 查看结果。

    通过_cat recovery API查看shrink进度,当无shrink相关的recovey,且集群状态健康,则shrink完成。

    • 查看shrink进度

      GET _cat/recovery?v&active_only

      当返回结果的index列没有等待shrink的索引时,说明无shrink相关的recovey。

    • 查看集群健康状态

      GET _cluster/health

      当返回结果中包含"status" : "green"时,说明集群状态健康。

常见问题

Q:为什么要使用硬链接,而不使用软链接?

A:通过软链接创建索引,待数据写入,将原索引删除后,目标索引数据也会被删除,而硬链接会保证索引的独立性。