Elasticsearch 索引迁移优化实战:从合并索引到原样导入
## 背景与目标
在 Elasticsearch 集群迁移过程中,我们需要将源 ES 的多个索引合并后导入到新的 ES 库中。具体需求如下:
- 索引合并规则:将 5 个源索引合并为 1 个目标索引
- 分片优化:目标索引的分片数从 2 个增加到 9 个(3 个节点,每个节点 3 个分片)
- 数据量:单个索引约 24GB,总计约 120GB 数据
方案演进过程
方案一:直接使用 elasticdump 串行迁移
尝试过程
最初尝试使用 elasticdump 直接将多个源索引导入到同一个目标索引:
# 串行执行多个索引的导入
elasticdump \--input="https://source:9200/scihub_1000_1199" \--output="https://target:9200/scihub_1000_1999" \--type=dataelasticdump \--input="https://source:9200/scihub_1200_1399" \--output="https://target:9200/scihub_1000_1999" \--type=data
# ... 继续导入其他索引
遇到的问题
问题描述:串行执行时,后面的 dump 操作会覆盖前面的结果,导致目标索引的文档数始终停留在 40 万左右,无法达到预期的合并效果。
原因分析:
- 当多个源索引中存在相同的文档 ID 时,后续导入会覆盖已存在的文档
elasticdump默认使用文档的原始_id,如果不同源索引中有相同 ID,就会发生覆盖
解决方案
虽然可以通过添加 ID 前缀来避免覆盖(使用 --transform 参数),但考虑到后续还有其他问题,我们决定尝试其他方案。
方案二:先导出到本地,合并后再导入
实施步骤
- 第一步:将源索引导出到本地 JSON 文件
- 第二步:合并多个 JSON 文件
- 第三步:将合并后的 JSON 导入目标 ES
遇到的问题
问题 1:合并流程耗时过长
- 单个索引的 JSON 文件约 24GB
- 5 个索引总计约 120GB
- 合并过程需要读取、解析、修改、写入大量数据
- 一次合并过程耗时达到天级别,严重影响迁移效率
问题 2:索引名修改耗时
- 导出的 JSON 文件中保留了源索引名(
_index字段) - 合并时需要修改所有文档的
_index字段为目标索引名 - 这个操作进一步增加了合并时间
优化尝试
使用 transformer 在导出时修改索引名
发现 elasticdump 支持 --transform 参数,可以在导出时直接修改索引名:
elasticdump \--input="https://source:9200/scihub_1000_1199" \--output="./data/scihub_1000_1199.json" \--type=data \--transform=