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


(Medcl) #1

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

关于版本升级,有很多种办法可以做到,这次 Advent 活动的第一篇,Mark Walkom 已有提及。原地升级固然速度很快,但是索引格式还是旧格式,数据结构依然还是旧的,无法应用新的特性,故无法发挥新版本的威力,

迁移任务

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

首先,假设我们已经部署好了新的 Elasticsearch 6.0 的集群,具体部署的细节这里就不展开了,这里有详细的文档

前提准备

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

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

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

设置新索引

将一个索引从旧的集群迁移到新的集群,需要考虑的因素很多,强烈建议使用升级助手(Upgrade Assistant)进行更加详细的检测,你需要安装 Kibana 和 X-Pack 插件,这里就不具体介绍了。

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

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

192.168.3.213:9200 上执行

GET medcl/_settings

返回的内容是:

{
  "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 上执行

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 上执行

GET medcl/_mapping

返回结果为即为 mapping 信息。

{
  "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 上执行

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

开始导入

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

127.0.0.1:9200 上执行

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

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

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

处理多个 Type

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

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

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 上执行

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

reindex 还有一些阈值等参数可以通过设置,具体的可以参照 reindex API 的文档

另外你可能还希望执行 shrink 操作合并分片数,这里是文档

写在最后

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