4. 索引与映射迁移策略
索引与映射迁移是 Elastic 平台升级或跨集群搬迁中最容易“卡住”的环节。数据本身可以复制,但映射一旦定义错误,写入、聚合、排序都会连锁失败。本节围绕四类典型问题展开:Mapping 变更、字段类型冲突、多类型索引拆分,以及 Reindex API 与远程 Reindex 的实战用法。
一、Mapping 变更:为什么不能直接改字段类型
Elasticsearch 的字段映射在索引创建后大部分是不可变的。例如把一个字段从 text 改成 keyword,或从 integer 改成 long,直接调用 PUT /index/_mapping 会报错。原因是底层 Lucene 的倒排索引、doc_values 和列式存储结构已经按旧类型构建,无法原地重写。
因此 Mapping 变更的正确路径是“新建索引 + 重新索引 + 别名切换”。常见可安全新增的内容包括:新增字段、为已有字段增加 multi-field(如 keyword 子字段)、调整 ignore_above、dynamic 等参数。而修改字段类型、分词器、doc_values 开关,则必须走重建流程。
二、字段类型冲突:迁移中最常见的“隐形炸弹”
类型冲突通常出现在两种场景:一是同一字段在不同索引中类型不一致,二是目标索引已有 Mapping 与源数据推断类型不符。例如源索引中 price 是 float,目标模板却定义为 keyword,Reindex 时该文档会失败并进入错误队列。
处理冲突前,先做一次全量类型盘点。可以用如下方式快速比对源与目标的字段类型:
GET /source_index/_mapping
GET /target_index/_mapping
# 对比字段类型差异(示例思路)
# 源: price -> float
# 目标: price -> keyword → 冲突,需要统一
冲突解决策略有三种:统一为目标类型(推荐,需确认业务语义)、使用 ingest pipeline 做类型转换(如 convert 处理器把字符串转数值)、保留为多字段(同时提供 text 与 keyword)。若源数据本身脏,例如数值字段混入 "N/A",应在 pipeline 中用 convert 的 ignore_missing 与 on_failure 兜底,避免整批失败。
三、多类型索引拆分
Elasticsearch 6.x 之前允许一个索引下多个 type,7.x 起彻底移除。迁移旧集群时,常见一个索引里混有 user、order、product 多种 type。正确做法是按 type 拆成独立索引,例如 legacy_user、legacy_order、legacy_product,再分别定义各自的 Mapping。
拆分时要注意:不同 type 的字段同名但类型不同,必须分别建模;文档 _id 可能重复,需加前缀或使用 _id 重写规则;跨 type 的父子关系要改为 join 字段或独立索引 + 应用层关联。拆分后建议用别名统一对外,例如 user 别名指向 legacy_user,减少应用改动。
四、Reindex API 与远程 Reindex
Reindex 是把源索引文档复制到目标索引的核心工具。基本用法:
POST _reindex?wait_for_completion=false
{
"source": {
"index": "legacy_order",
"_source": ["order_id", "amount", "created_at"]
},
"dest": {
"index": "order_v2",
"pipeline": "order_convert_pipeline"
},
"conflicts": "proceed"
}
关键参数说明:wait_for_completion=false 返回 task ID,适合大数据量异步执行;_source 过滤只迁移必要字段,降低网络与存储开销;pipeline 在写入前做类型转换与字段清洗;conflicts: proceed 让版本冲突不中断任务,但需后续核对。
远程 Reindex 用于跨集群迁移,需在目标集群的 elasticsearch.yml 中配置白名单:
reindex.remote.whitelist: "source-host:9200"
然后调用:
POST _reindex?wait_for_completion=false
{
"source": {
"remote": {
"host": "http://source-host:9200",
"username": "reindex_user",
"password": "******"
},
"index": "legacy_user",
"size": 1000
},
"dest": { "index": "user_v2" }
}
远程 Reindex 的 size 控制每批拉取量,默认 1000,网络不稳定时可调小。注意远程集群版本不能高于目标集群,且需保证源集群有足够读权限。
五、实战校验与判断依据
迁移完成后不能只看“任务成功”。建议核对四项:文档总数(源与目标 _count 一致)、抽样字段值(随机取 10 条比对关键字段)、聚合结果(对数值字段做 sum/avg 对比)、错误队列(查看 _tasks 返回的 failures)。若失败数不为 0,需按 _index、_id 定位并重跑。
_source 必须开启,否则无法重建。最后,别名切换是迁移的“最后一公里”。建议用 _aliases 原子操作,把读写别名一次性指向新索引,避免应用侧出现双写或读空窗。切换后保留旧索引至少一个版本周期,确认无回滚需求后再删除。