什么时候需要重建索引
以下情况需要执行 reindex:
- 索引的 mappings 发生变更
- 索引的 settings 发生变更
- 集群内或集群间需要做数据迁移
数据预处理
使用 Ingest Pipeline 预处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| PUT _ingest/pipeline/split_xxx { "processors": [ { "split": { "field": "xxx", "separator": "," }, { "set": { "field": "xxx", "value": "0" } } } ] }
# reindex POST _reindex { "source": { "index": "index_old" }, "dest": { "index": "index_new", "pipeline": "split_xxx" } }
|
使用 Script 脚本处理数据
ES 支持的 Painless 脚本非常强大,以下是一个简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| POST _reindex { "source": { "index": "index_old" }, "dest": { "index": "index_new" }, "script": { "source": "ctx._source.age += 2", "lang": "painless" } }
|
字段重命名
使用 Script 将 name 字段重命名为 newName:
1 2 3 4 5 6 7 8 9 10 11 12 13
| POST _reindex { "source": { "index": "index_old" }, "dest": { "index": "index_new" }, "script": { "source": "ctx._source.newName = ctx._source.remove(\"name\")", "lang": "painless" } }
|
只同步部分字段
只将指定字段从源索引复制到目标索引:
1 2 3 4 5 6 7 8 9 10
| POST _reindex { "source": { "index": "index_old", "_source": ["name", "age"] }, "dest": { "index": "index_new" } }
|
只创建目标索引中不存在的文档
1 2 3 4 5 6 7 8 9 10
| POST _reindex { "source": { "index": "index_old" }, "dest": { "index": "index_new", "op_type": "create" } }
|
设置批次大小
reindex 底层使用 scroll,默认每批 1000 条,可按需调大:
1 2 3 4 5 6 7 8 9 10
| POST _reindex { "source": { "index": "index_old", "size": 5000 }, "dest": { "index": "index_new" } }
|
遇到版本冲突时继续执行
1 2 3 4 5 6 7 8 9 10 11
| POST _reindex { "conflicts": "proceed", "source": { "index": "index_old" }, "dest": { "index": "index_new", "op_type": "create" } }
|
只 reindex 符合条件的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| POST _reindex { "source": { "index": "index_old", "query": { "term": { "name.keyword": { "value": "冬哥" } } } }, "dest": { "index": "index_new" } }
|
排除不想同步的字段
1 2 3 4 5 6 7 8 9 10 11 12
| POST _reindex { "source": { "index": "index_old", "_source": { "excludes": ["name"] } }, "dest": { "index": "index_new" } }
|
不停机 reindex(使用 alias)
Alias
一个索引可以接受多个别名,一个别名也可以映射到多个索引;别名可以关联 filter 并自动应用到检索。别名不能与索引同名。同一 API 请求中,移除和添加别名是原子操作,无需担心短暂的空窗期。
1 2 3 4 5 6 7 8 9
| # 添加别名示例: PUT /my_index_name/_alias/alias_name
POST /_aliases { "actions": [ { "add": { "index": "my_index__name_v2", "alias": "alias_name" }} ] }
|
步骤:首先确保旧索引有别名且业务方通过别名访问,然后新建索引并将旧索引数据 reindex 过去:
1 2 3 4 5 6 7 8 9
| POST _reindex { "source": { "index": "old_index" }, "dest": { "index": "new_index" } }
|
最后原子地将别名从旧索引切换到新索引:
1 2 3 4 5 6 7
| POST /_aliases { "actions": [ { "remove": { "index": "my_index_name_v1", "alias": "alias_name" }}, { "add": { "index": "my_index__name_v2", "alias": "alias_name" }} ] }
|
停机 reindex(未建别名的情况)
操作步骤:
- 创建一个中间索引
- 将源索引数据(含 mapping)备份到中间索引
- 查询确认数据是否 copy 成功
- 删除有问题的源索引
- 重新创建同名索引(★ 字段类型修改正确 ★)
- 从中间索引还原数据到源索引
- 删除中间索引
建中间索引
可在 Kibana 索引管理页面直接复制 mapping。ES 7 之后不支持 type,记得去掉 mapping 下的 _doc 层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| PUT prod-sopei-reindex { "mappings": { "dynamic_templates": [ { "message_field": { "path_match": "message", "match_mapping_type": "string", "mapping": { "norms": false, "type": "text" } } }, { "string_fields": { "match": "*", "match_mapping_type": "string", "mapping": { "fields": { "keyword": { "ignore_above": 256, "type": "keyword" } }, "norms": false, "type": "text" } } } ], "properties": { "@timestamp": { "type": "date" }, "@version": { "type": "keyword" } ... } } }
|
将源索引数据 copy 到中间索引(异步)
wait_for_completion=false 表示异步执行。注意:Kibana 默认超时 30s,可修改 kibana.yml 中的 elasticsearch.requestTimeout(治标不治本)。
1 2 3 4 5 6 7 8 9 10 11
| POST _reindex?wait_for_completion=false { "source": { "index": "xxx-20210916" }, "dest": { "index": "xxx-reindex" } } # 查询reindex任务进度 GET _tasks?detailed=true&actions=*reindex
|

查询确认数据是否 copy 成功
删除旧索引
重新创建同名索引(★ Mapping 取自新索引 ★)
1 2 3 4
| PUT xxx-20210916 { ... }
|
还原数据到源索引
1 2 3 4 5 6 7 8 9 10 11
| POST _reindex?wait_for_completion=false { "source": { "index": "xxx-reindex" }, "dest": { "index": "xxx-20210916" } } # 查询reindex任务进度 GET _tasks?detailed=true&actions=*reindex
|
删除中间索引