# Dec 8th, 2017: \[CN\]\[Elasticsearch\] 使用 reindex API 迁移数据到 6.x 集群

**URL:** <https://discuss.elastic.co/t/dec-8th-2017-cn-elasticsearch-reindex-api-6-x/110257>\
**Category:** Advent Calendar\
**Created:** [December 7, 2017, 1:00pm UTC](https://discuss.elastic.co/t/dec-8th-2017-cn-elasticsearch-reindex-api-6-x/110257 "2017-12-07T13:00:15Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![medcl.net](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/medcl.net/32/4414_2.png) [@medcl.net](https://discuss.elastic.co/u/medcl.net)\
**Post date:** [December 7, 2017, 1:00pm UTC](https://discuss.elastic.co/t/dec-8th-2017-cn-elasticsearch-reindex-api-6-x/110257/1 "2017-12-07T13:00:15Z")

</div>

Elastic Stack 6.0 已经正式发布了，包含了很多激动人心的特性，相信有一些特性也是你非常感兴趣的，所以要不要考虑升级到最新的 6.0 版本呢？

关于版本升级，有很多种办法可以做到，这次 Advent 活动的[第一篇](https://discuss.elastic.co/t/dec-1st-2017-en-elastic-stack-upgrading-to-6-0-0/109300/2)，Mark Walkom 已有提及。原地升级固然速度很快，但是索引格式还是旧格式，数据结构依然还是旧的，无法应用新的特性，故无法发挥新版本的威力，

# 迁移任务

所以今天我就来说说如果使用 `reindex` API 来进行 Elasticsearch 集群数据的迁移。假设新的集群 IP 为 `127.0.0.1`，旧数据所在集群为： `192.168.3.213`，我们要迁移的索引名是：`medcl`，里面有一些数据，今天的任务就是将这些数据从旧集群迁移到新的集群。

首先，假设我们已经部署好了新的 Elasticsearch 6.0 的集群，具体部署的细节这里就不展开了，这里有详细的[文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/_installation.html)。

# 前提准备

因为我们的新集群需要访问旧集群的数据，首先需要修改新集群的 Elasticsearch 配置文件，设置我们要访问的集群的白名单，打开 Elasticsearch (`127.0.0.1:9200`) 的配置文件：`config/elasticsearch.yml`，新增一行配置：

```auto
reindex.remote.whitelist: ["192.168.3.213:9200"]

```

新的集群每个节点都进行同样的修改，我们这里只有一个节点，修改并重启 Elasticsearch 使配置文件生效即可。

# 设置新索引

将一个索引从旧的集群迁移到新的集群，需要考虑的因素很多，强烈建议使用升级助手（[Upgrade Assistant](https://www.elastic.co/guide/en/kibana/6.0/xpack-upgrade-assistant.html)）进行更加详细的检测，你需要安装 Kibana 和 X-Pack 插件，这里就不具体介绍了。

关于新的 6.0 接口是否兼容你之前的旧的业务调用代码，请进一步进行测试，在这里只考虑数据的迁移。

导入数据之前，你需要手动配置好新索引的 `settings` 和 `mapping` 信息，这里有个小技巧就是可以先从旧的索引里面获得旧的索引设置，然后再创建到新的索引里面。

在 `192.168.3.213:9200` 上执行

```auto
GET medcl/_settings

```

返回的内容是：

```auto
{
  "medcl": {
    "settings": {
      "index": {
        "number_of_shards": "5",
        "provided_name": "medcl",
        "creation_date": "1512449188767",
        "analysis": {
          "analyzer": {
            "pinyin_analyzer": {
              "tokenizer": "my_pinyin"
            }
          },
          "tokenizer": {
            "my_pinyin": {
              "lowercase": "true",
              "keep_original": "true",
              "remove_duplicated_term": "true",
              "keep_separate_first_letter": "false",
              "type": "pinyin",
              "limit_first_letter_length": "16",
              "keep_full_pinyin": "true"
            }
          }
        },
        "number_of_replicas": "1",
        "uuid": "Rs0tTFibQSuqBVQ5xokyPQ",
        "version": {
          "created": "6000099"
        }
      }
    }
  }
}

```

我们可以返回的结果基础上，移除最为层的 `medcl` 节点，去除 `UID` 等版本信息，保留 `analysis` 信息。  
同时为了提高速度，我们还可以将分片数的设置大一点，后面可以执行 `shrink` 操作合并分片，另外再设置副本是为`0`，同时可以禁用`refresh`，目的都是为了提高索引速度。  
然后在最新的集群上面执行下面的索引创建操作，如下：

在 `127.0.0.1:9200` 上执行

```auto
PUT medcl
{
    "settings": {
      "index": {
        "number_of_shards": 10,
        "analysis": {
          "analyzer": {
            "pinyin_analyzer": {
              "tokenizer": "my_pinyin"
            }
          },
          "tokenizer": {
            "my_pinyin": {
              "lowercase": "true",
              "keep_original": "true",
              "remove_duplicated_term": "true",
              "keep_separate_first_letter": "false",
              "type": "pinyin",
              "limit_first_letter_length": "16",
              "keep_full_pinyin": "true"
            }
          }
        },
        "number_of_replicas": 0,
        "refresh_interval":-1
      }
    }
}

```

当然还有一些其他层面关于索引的优化，这里就不展开了，感兴趣的可以进一步了解。

下面继续进行 `mapping` 的导入。

在 `192.168.3.213:9200` 上执行

```auto
GET medcl/_mapping

```

返回结果为即为 `mapping` 信息。

```auto
{
  "medcl": {
    "mappings": {
      "folks": {
        "properties": {
          "name": {
            "type": "keyword",
            "fields": {
              "pinyin": {
                "type": "text",
                "boost": 10,
                "term_vector": "with_offsets",
                "analyzer": "pinyin_analyzer"
              }
            }
          }
        }
      }
    }
  }
}

```

从 6.0 开始，我们只允许一个 type 了，我们可以随手重命名新的 type 为 `doc`，如果你的查询里面使用了`_type`字段，也需要注意进行相应的调整，我们现在基于旧的 mapping （这里只需要保留 `properties` 节点）修改之后的新的 mapping 在新的集群上面 `127.0.0.1` 创建 mapping：

在 `127.0.0.1:9200` 上执行

```auto
PUT medcl/doc/_mapping
{
  "properties": {
    "name": {
      "type": "keyword",
      "fields": {
        "pinyin": {
          "type": "text",
          "boost": 10,
          "term_vector": "with_offsets",
          "analyzer": "pinyin_analyzer"
        }
      }
    }
  }
}

```

# 开始导入

新的 `settings` 和 `mapping` 导入好了之后，就可以开始进行数据的导入了，这里自然就要用到我们的 `reindex` API 了。

在 `127.0.0.1:9200` 上执行

```auto
POST _reindex
{
  "source": {
    "remote": {
      "host": "http://192.168.3.213:9200"
    },
    "index": "medcl"
  },
  "dest": {
    "index": "medcl",
    "type":"doc"
  }
}

```

注意，如果旧索引服务器需要身份认证（比如安装了 X-Pack），记得加上对应的用户名和密码信息，`source` 和 `target` 即分别是旧索引和新索引的名称，假如你愿意，完全可以相同，这里都是 `medcl`。

如果你的数据比较多，这里有个小技巧，就是在 URL 的参数里面加上 `wait_for_completion=false`，这样 reindex 会在后台继续执行任务。

# 处理多个 Type

Elasticsearch 从 6.0 开始，不支持多个 `type` 了，所以如果你的旧索引有多个 `type` 的话，这样直接 reindex 会失败的。

怎么解决呢？这里有个小技巧就是可以分别按 `type` 来进行导入，reindex 支持查询条件来过滤要导入的数据，也就是一个 `type` 一个新索引，同样记得先创建好索引并进行相应的 setting 和 mapping 设置。

```auto
POST _reindex
{
  "source": {
    "remote": {
      "host": "http://192.168.3.213:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "source",
    "query": {
      "match": {
        "_type": "type1"
      }
    }
  },
  "dest": {
    "index": "new-index-type1"
  }
}

```

# 最后的操作

OK, 到这里我们的数据就导入完毕了，你还需要开启 `refresh` 和恢复副本等操作。

在 `127.0.0.1:9200` 上执行

```auto
PUT medcl/_settings
{
    "settings": {
      "index": {
        "number_of_replicas": 1,
        "refresh_interval":"1s"
      }
    }
}

```

reindex 还有一些阈值等参数可以通过设置，具体的可以参照 `reindex` API 的[文档](https://www.elastic.co/guide/en/elasticsearch/reference/6.0/docs-reindex.html)。

另外你可能还希望执行 `shrink` 操作合并分片数，这里是[文档](https://www.elastic.co/guide/en/elasticsearch/reference/6.0/indices-shrink-index.html)。

# 写在最后

本文是 Elastic Advent Calendar 的第 8 篇，主要介绍了如果使用 `reindex` API 来进行数据的迁移，将旧集群的数据迁移到最新的 6.0 集群，希望对你有帮助。

---

<div class="post-metadata">

**Author:** ![warkolm](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/warkolm/32/39224_2.png) [@warkolm](https://discuss.elastic.co/u/warkolm)\
**Post date:** [August 23, 2018, 8:31am UTC](https://discuss.elastic.co/t/dec-8th-2017-cn-elasticsearch-reindex-api-6-x/110257/2 "2018-08-23T08:31:22Z")

</div>


