# 通过ESM实现Elasticsearch集群间数据迁移
#### 应用场景
ESM（Elasticsearch Migration Tool）是一个开源的Elasticsearch集群迁移工具。它支持不同版本的Elasticsearch之间的数据迁移，并且可以通过配置Scroll API的参数来控制迁移速率，以适应不同的网络环境和业务需求。以下是ESM实现Elasticsearch集群间数据迁移的应用场景：
- 跨版本迁移：在Elasticsearch集群需要升级到新版本时，ESM可以帮助平滑迁移数据，确保升级过程中数据的完整性和可用性。
- 集群合并：当企业需要将多个Elasticsearch集群的数据整合到一个集群中以简化管理时，ESM可以高效地完成这一任务。
- 服务迁移上云：企业可以将自建的Elasticsearch服务迁移至云平台，以利用云服务的弹性扩展、简化维护和成本效益。
- 变更服务提供商：如果企业当前使用的是第三方Elasticsearch服务，但出于成本、性能或其他战略考虑，希望更换服务提供商至华为云。
 
#### 方案架构
图1迁移流程   
![](https://support.huaweicloud.com/bestpractice-css/figure/zh-cn_image_0000002106434625.png "点击放大")
通过ESM工具实现Elasticsearch集群间数据迁移的迁移流程如[图1]所示。
1. 在Linux虚拟机上安装ESM迁移工具。
2. 通过ESM迁移命令，将源集群的索引数据迁移至目标集群。
 
#### 方案优势
- 跨版本兼容性：ESM支持不同版本的Elasticsearch集群间的数据迁移，包括从老版本迁移到新版本。
- 简化操作：ESM使用简单方便，使用Go语言开发，只需下载编译包安装即可使用。
- 性能控制：在迁移过程中，可以通过配置Scroll API的参数来控制迁移速率，优化迁移性能。
- 灵活的迁移方案：ESM提供了灵活的迁移方案，包括全量迁移和增量迁移，以适应不同的业务需求。
- 开源免费：作为一个开源工具，ESM代码托管在GitHub上，用户可以免费使用。
 
#### 性能影响
ESM迁移集群的工作原理基于Scroll API，此API能够高效地从源集群查找索引数据，并批量同步至目标集群。这一过程可能会对源集群性能产生影响，具体影响程度取决于目标集群对源集群的读取速度，ESM通过配置"-w"和"-b"可以调整迁移速度，配置指导请参见[esm](https://github.com/medcl/esm)官方文档。
由于ESM能够迅速从源集群读取数据，可能会对源集群的性能产生影响。因此，建议在业务低峰时段进行数据迁移，以监控源集群CPU和内存的性能指标变化。通过调整迁移速度和选择适宜的迁移时间窗口，可以有效控制性能影响。对于涉及大量数据迁移或资源占用较高的集群，特别推荐在业务低峰期执行数据迁移，以确保源端业务操作不受影响。
#### 约束限制
集群迁移过程中，源集群的索引数据不能增删改，否则会导致迁移失败，或是迁移后的源集群数据和目标集群数据内容不一致。
#### 前提条件
- 源Elasticsearch集群和目标Elasticsearch集群处于可用状态。
- 集群间需要保证网络连通。
  - 如果源集群和目标集群在同一VPC，则网络已连通。
  
  - 如果源集群和目标集群在不同VPC，则需要先打通VPC网络。具体操作请参见[配置Elasticsearch集群路由](https://support.huaweicloud.com/usermanual-css/css_01_0279.html)。
  
  - 如果是自建Elasticsearch集群迁移至华为云，则可以通过给自建Elasticsearch集群配置公网访问打通网络。
  
  - 如果是第三方Elasticsearch集群迁移至华为云，则需要建立企业内部数据中心到华为云的VPN通道或专线。
   
- 确认集群的索引已开启"_source"。 集群索引的"_source"默认是开启的。执行命令GET {index}/_search，当返回的搜索结果中包含"_source"字段时表示已开启。
  
 
#### 获取Elasticsearch集群信息
在迁移集群前，需要先获取必备的集群信息，用于配置迁移任务。
表1需要获取的Elasticsearch集群信息 
| 集群来源                                                                       || 要获取的信息                                                                                                                                                                                                                                        | 获取方式                                                                                                                                                                                                                                                                                                                                                            |
|:---|---|:---|:---|
| 源集群     | 华为云Elasticsearch集群  | - 源集群的访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）         | - 获取集群名称和访问地址请参见[3](https://support.huaweicloud.com/bestpractice-css/css_07_0009.html#ZH-CN_TOPIC_0000001971547281__li92051018102011)。  - 用户名和密码请联系服务管理员获取。   |
| 源集群     | 自建Elasticsearch集群  | - 源集群的公网访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）   | 联系服务管理员获取。                                                                                                                                                                                                                                                                                                                                                      |
| 源集群     | 第三方Elasticsearch集群  | - 源集群的访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）         | 联系服务管理员获取。                                                                                                                                                                                                                                                                                                                                                        |
| 目标集群 | 华为云Elasticsearch集群 | - 目标集群的访问地址  - 访问目标集群的用户名和密码（仅安全集群涉及）            | - 获取访问地址请参见[3](https://support.huaweicloud.com/bestpractice-css/css_07_0009.html#ZH-CN_TOPIC_0000001971547281__li92051018102011)。  - 用户名和密码请联系服务管理员获取。   |
   
源集群的来源不同，获取信息的方式不同，此处仅介绍如何获取华为云Elasticsearch集群的信息。
1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
2. 在左侧导航栏，选择"集群管理 \> Elasticsearch"。
3. 在集群列表，选择目标集群，获取集群名称和访问地址。
   图2获取集群信息   
   ![](https://support.huaweicloud.com/bestpractice-css/figure/zh-cn_image_0000001969281924.png "点击放大") 
 
#### 准备迁移虚拟机
创建ECS用于迁移Elasticsearch集群。
1. 购买Linux ECS，"镜像"选择CentOS 7系列，"虚拟私有云"和目标集群保持一致。购买操作指导请参见[快速购买和使用Linux ECS](https://support.huaweicloud.com/qs-ecs/ecs_01_0103.html)。
2. 测试ECS和源集群、目标集群的连通性。 在ECS执行如下命令测试连通性，当正常返回集群信息时表示已经连通。
   ```
   # 非安全模式的集群
   curl http://[ip]:9200
   # 安全模式+HTTP访问的集群
   curl -ik http://[ip]:9200 -u [username]:[password]
   # 安全模式+HTTPS访问的集群
   curl -ik https://[ip]:9200 -u [username]:[password]
   ```
   
 
#### 通过ESM迁移集群
1. 访问[ESM下载地址](https://github.com/medcl/esm/releases/tag/v0.6.1)，下载"migrator-linux-amd64"软件包。
2. 通过SCP工具将下载的"migrator-linux-amd64"软件包上传到Linux ECS的执行路径下。
3. 在Linux ECS的执行路径下执行命令，将源集群的索引结构和数据迁移到目标集群。
   ```
   # 索引全量迁移
   ./migrator-linux-amd64 -s http://source:9200 -d http://dest:9200 -x index_name -m admin:password -n admin:password --copy_settings --copy_mappings -w 5 -b 10
   #索引增量迁移
   ./migrator-linux-amd64 -s http://source:9200 -d http://dest:9200 -x index-test -m admin:password -n admin:password -w 5 -b 10 -q "timestamp:[\"2022-01-17 03:41:20\" TO \"2022-01-22 03:41:20\"]"
   ```
   迁移命令的常用参数说明请参见[表2]，更多详细参数说明请参见[ESM文档](https://github.com/medcl/esm/blob/master/README.md)。
    表2常用参数说明 
   | 参数                   | 示例                                                                                                                           | 说明                                                                                                                                                                                                                                                                                                                                                              |
   |:---|:---|:---|
   | -s, --source=         | http://source:9200                                                                                                            | 源Elasticsearch集群访问地址。 - 集群使用HTTP协议，则配置为http://xx.xx.xx.xx:9200  - 集群使用HTTPS协议，则配置为https://xx.xx.xx.xx:9200   |
   | -d, --dest=         | http://dest:9200                                                                                                            | 目标Elasticsearch集群访问地址。 - 集群使用HTTP协议，则配置为http://xx.xx.xx.xx:9200  - 集群使用HTTPS协议，则配置为https://xx.xx.xx.xx:9200      |
   | -x, --src_indexes=  | index_name index1,index2 index\* | 源集群待迁移索引名，支持逗号分隔和通配符\*。                                                                                                                                                                                                                                                                                                                                         |
   | -y, --dest_index=   | index_name_rename                                                                                                           | 目标集群索引名，支持单索引名称，如果不配置则和源索引名称相同。                                                                                                                                                                                                                                                                                                                                   |
   | -m, --source_auth= | admin:password                                                                                                              | 访问源Elasticsearch集群的用户名和密码，仅安全集群涉及。                                                                                                                                                                                                                                                                                                                             |
   | -n, --dest_auth=     | admin:password                                                                                                             | 访问目标Elasticsearch集群的用户名和密码，仅安全集群涉及。                                                                                                                                                                                                                                                                                                                             |
   | -w, --workers=    | 5                                                                                                                           | 读取源端数据速率控制参数，Bulk读取数据并发线程数。 默认值：1                                                                                                                                                                                                                                                                                |
   | -b, --bulk_size=    | 10                                                                                                                          | 读取源端数据速率控制参数，Bulk一次读取数据的数据大小。 默认值：5MB                                                                                                                                                                                                                                                                               |
   | -q, --query=       | "timestamp:\[\\"2022-01-17 03:41:20\\" TO \\"2022-01-22 03:41:20\\"\]"                                                     | 定义查询条件，支持Elasticsearch的DSL查询语法。 如果全量数据导出，则无需配置该参数；如果选择部分数据导出，则可以通过配置该参数过滤数据。 设置该参数时要注意查询条件中的字段必须是索引中存在的字段，否则无法正常匹配数据。                                                                                                                                               |
   | --sliced_scroll_size | 4                                                                                                                         | 读取源端数据速率控制参考，Bulk Scroll中sliced的大小。 默认值：1                                                                                                                                                                                                                                                                           |
   | --copy_settings       | -                                                                                                                           | 迁移源端索引的settings。                                                                                                                                                                                                                                                                                                                                                 |
   | --copy_mappings    | -                                                                                                                          | 迁移源端索引的mappings。                                                                                                                                                                                                                                                                                                                                                 |
   | --buffer_count=     | -                                                                                                                           | 迁移虚拟机缓存在内存中的文档数量。 默认值：10w                                                                                                                                                                                                                                                                                           |
      
   
4. 数据迁移完成后，使用以下命令分别在源集群和目标集群中获取文档个数，并对比结果以确认数据一致性。
   ```
   # 非安全模式的集群
   curl http://[ip]:9200/[index_name]/_count 
     
   # 安全模式+HTTP访问的集群
   curl -ik -u [username]:[password] http://[ip]:9200/[index_name]/_count
   # 安全模式+HTTPS访问的集群
   curl -ik -u [username]:[password] https://[ip]:9200/[index_name]/_count
   ```
   
 
#### 常见问题
- **迁移过程出现报错"out of memory"怎么办？**
  迁移过程中出现报错"out of memory"，表示迁移虚拟机内存溢出，有如下解决方案：
  - 可能是ECS虚拟机的配置不够，建议升级ECS规格，操作指导请参见[变更单台ECS规格](https://support.huaweicloud.com/usermanual-ecs/zh-cn_topic_0013771092.html)。
  
  - 调整ESM的迁移速度，通过在迁移命令中减小"buffer_count"参数，限制内存中的文档数量。
   
- **迁移完成后，为什么源集群和目标集群的索引数据存储量不一致？**
  ESM迁移集群后，两个集群的数据存储量不一致是正常的，这是由Elasticsearch的内部存储机制决定的。Elasticsearch存储是有多个shard，每个shard又有多个segment，由于ESM迁移是把源集群数据写入到目标集群，会导致在目标集群重新生成segment和shard，由于segment和shard都会对数据有膨胀，不同集群的segment的shard不同，数据量也不同，如果需要比较数据一致性，则需要对比文档个数的多少，而不是对比数据大小。
  
 
