背景
在初期设计es索引文档的时候考虑不是很周全,会多出很多无效字段。如果不删除或禁用对后续数据增量以及文档维护会有不良影响。
技术实现
使用 _reindex
1.执行Reindex
# 复制旧索引数据到新索引
POST _reindex
{
"source": {
"index": "old_index_name"
},
"dest": {
"index": "new_index_name"
}
}
优化参数
POST _reindex?wait_for_completion=false # 异步执行
{
"source": {
"index": "old_index_name",
"size": 1000 # 分批处理(默认 1000)
},
"dest": {
"index": "new_index_name",
"op_type": "create" # 防止覆盖已存在文档
}
}
2.删除旧索引
DELETE /old_index_name
3.更新索引别名
# 创建别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "new_index_name",
"alias": "index_alias"
}
}
]
}
# 验证别名
GET /_cat/aliases
风险
一.数据一致性风险
1.源索引写入冲突
-
场景:重建过程中源索引持续写入新数据,导致新旧索引数据不一致
-
解决方案
-
全量+增量迁移
# 1. 全量迁移 POST _reindex { "source": { "index": "old_index" }, "dest": { "index": "new_index" } } # 2. 增量迁移(假设存在时间字段 @timestamp) POST _reindex { "source": { "index": "old_index", "query": { "range": { "@timestamp": { "gte": "now-10m" # 同步最近10分钟的数据 } } } }, "dest": { "index": "new_index" } }
-
使用别名切换
# 1. 创建临时别名指向旧索引 POST /_aliases { "actions": [ { "add": { "index": "old_index", "alias": "temp_alias" } } ] } # 2. 重建索引后切换别名 POST /_aliases { "actions": [ { "remove": { "index": "old_index", "alias": "temp_alias" } }, { "add": { "index": "new_index", "alias": "temp_alias" } } ] }
-
2.字段类型冲突
-
场景:源索引目标索引的字段类型不匹配(如源为
text
,目标为keyword
) -
解决方案
# 1. 提前创建目标索引并指定映射 PUT /new_index { "mappings": { "properties": { "field1": { "type": "keyword" } } } } # 2. 执行 Reindex 时忽略冲突 POST _reindex { "source": { "index": "old_index" }, "dest": { "index": "new_index" }, "conflicts": "proceed" }
二.性能与资源风险
1.集群负载过高
-
重建大索引(如 TB 级) 导致 CPU/内存 使用率飙升,影响其他业务
-
解决方案:
- 分批次处理
POST _reindex?wait_for_completion=false&slice=0&num_slices=5 { "source": { "index": "old_index", "size": 10000 }, "dest": { "index": "new_index" } }
- 降低副本数
PUT /new_index/_settings { "number_of_replicas": 0 }
2.磁盘空间不足
- 场景:重建索引导致磁盘使用率超过85%,触发 es 限流
三.案例
-
reindex任务中途失败
-
源索引与目标索引的文档数量相同,但部分字段值不同
总结
通过以下策略可有效降低风险:
- 分阶段操作:全量迁移 > 增量同步 > 别名切换
- 资源隔离:使用专有节点或临时扩容集群
- 自动化验证:通过脚本对比源与目标索引的数据哈希值
- 灰度发布:先重建部分索引(如 10% 数据),验证无误后再全量执行