Elasticsearch:Split index API - 把一个大的索引分拆成更多分片

在我们实际使用 Elasticsearch 时,随着时间的推移,我们会发现有扩容的必要。这个可能由于我们在刚开始创建项目认识不足。我们需要更多的 primary shards,这样可以提高 ingest 的速度。那么我们有什么办法来把之前的一个大的索引变成更多的小的索引呢?这个答案就是 split index API。它的基本用法如下:

POST /my-index-000001/_split/split-my-index-000001
{
  "settings": {
    "index.number_of_shards": 2
  }
}

它有两种形式的接口:

POST /<index>/_split/<target-index>

PUT /<index>/_split/<target-index>

在我们操作之前,我们有如下的前提条件:

我们可以通过如下的方法来把一个索引变为 read-only:

PUT /my_source_index/_settings
{
  "settings": {
    "index.blocks.write": true 
  }
}

拆分索引 API 允许你将现有索引拆分为新索引,在该索引中,每个原始主 shard 在新索引中均拆分为两个或多个主 shard。

索引可拆分的次数(以及每个原始碎片可拆分为的碎片数量)由 index.number_of_routing_shards 设置确定。 路由分片的数量指定哈希空间,该空间在内部用于以一致的哈希在各个 shard 之间分发文档。 例如,将 number_of_routing_shards 设置为30(5 x 2 x 3)的5个 shard 索引可以拆分为 2 或 3。换句话说,可以如下拆分:

  • 5→10→30(拆分依次为2和3)
  • 5→15→30(拆分依次为3和2)
  • 5→30(拆分6)

 

动手实践

准备数据

在今天的教程中,我们将使用 Kibana 自带的索引来进行展示。打开 Kibana 界面:

点击 Add data:

这样我们的样本数据就导入进 Elasticsearch 了。通过上面的操作,我们在 Elasticsearch 中将生成一个叫做 kibana_sample_data_flights 的索引。

 

使用 split index API 来拆分索引

按照要求,我们首先把索引变为只读:

PUT kibana_sample_data_logs/_settings
{
  "blocks.write": true
}

在 Kibana  中运行上面的指令。我们可以通过如下的指令来进行查询:

GET kibana_sample_data_logs/_settings

上面的指令显示:

{
  "kibana_sample_data_logs" : {
    "settings" : {
      "index" : {
        "number_of_shards" : "1",
        "auto_expand_replicas" : "0-1",
        "blocks" : {
          "write" : "true"
        },
        "provided_name" : "kibana_sample_data_logs",
        "creation_date" : "1602127165075",
        "number_of_replicas" : "0",
        "uuid" : "oyJwGhQATvCil2rWAC6nqg",
        "version" : {
          "created" : "7080099"
        }
      }
    }
  }
}

上面显示 blocks.write 为 true,也即我们不可以再向这个索引写入任何的数据了。从上面我们也可以看出来,我们的当前的索引只有一个 primary shard。这个可以从 number_of_shards 为 1 可以看出来。

我们在 Kibana 中打入如下的指令:

POST kibana_sample_data_logs/_split/kibana_sample_data_logs_split
{
  "settings": {
    "index.number_of_shards": 2
  }
}

在上面,我们把 kibana_sample_data_logs 拆分为 2 个㊗️ shards,并且我们的目标索引的名字为:kibana_sample_data_logs_split。上面的命令的返回值为:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "kibana_sample_data_logs_split"
}

我们可以通过如下的命令来进行查看过程:

GET _cat/recovery/kibana_sample_data_logs_split

上面显示的结果为:

index                         shard time  type         stage source_host source_node target_host target_node repository snapshot files files_recovered files_percent files_total bytes bytes_recovered bytes_percent bytes_total translog_ops translog_ops_recovered translog_ops_percent
kibana_sample_data_logs_split 0     484ms local_shards done  n/a         n/a         127.0.0.1   node1       n/a        n/a      0     0               100.0%        15          0     0               100.0%        11573815    0            0                      100.0%
kibana_sample_data_logs_split 1     503ms local_shards done  n/a         n/a         127.0.0.1   node1       n/a        n/a      0     0               100.0%        15          0     0               100.0%        11573815    0            0                      100.0%

上面显示100%已经完成。

我们可以通过如下的方法来进行比较索引的数量:

GET kibana_sample_data_logs/_count

它显示:

{
  "count" : 14074,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  }
}

我们用如下的方法来查看 kibana_sample_data_logs_split 的设置:

GET kibana_sample_data_logs_split/_settings
{
  "kibana_sample_data_logs_split" : {
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "initial_recovery" : {
              "_id" : null
            }
          }
        },
        "number_of_shards" : "2",
        "routing_partition_size" : "1",
        "auto_expand_replicas" : "0-1",
        "blocks" : {
          "write" : "true"
        },
        "provided_name" : "kibana_sample_data_logs_split",
        "resize" : {
          "source" : {
            "name" : "kibana_sample_data_logs",
            "uuid" : "oyJwGhQATvCil2rWAC6nqg"
          }
        },
        "creation_date" : "1602127847864",
        "number_of_replicas" : "0",
        "uuid" : "rhs6k0P6QNudSVO1MauQZA",
        "version" : {
          "created" : "7080099",
          "upgraded" : "7080099"
        }
      }
    }
  }
}

上面显示 number_of_shards 为2,表示有2个主 shard。我们可以使用如下命令来进行查看文档的数量:

GET kibana_sample_data_logs_split/_count

上面的命令显示:

{
  "count" : 14074,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  }
}
GET _cat/shards/kibana_sample_data_logs_split?v

上面的命令显示:

index                         shard prirep state   docs store ip        node
kibana_sample_data_logs_split 1     p      STARTED 7076 4.8mb 127.0.0.1 node1
kibana_sample_data_logs_split 0     p      STARTED 6998 4.7mb 127.0.0.1 node1

我们可以看到有两个 primary shard。

如果我们想把上面的拆分的索引重新变成一个大的索引的话,那么请阅读我的另外一篇文章 “通过 shrink API 减少 shard 数量来缩小 Elasticsearch 索引”。