当项目初期决定好存储某种数据时,在创建索引的时候就需要将数据结构确定下来,于此同时索引的设定和其他配置将不能改变,如果需要改变数据结构则需要重新创建索引
一般博主遇到以下几个场景会出现需要重建索引:
扩容节点数量,有些数据需要调整分片数量
分词器词库更新,已生成索引的数据不会采用新的分词规则
新增需要索引的字段
此处介绍下使用elasticsearch的reindex+索引别名来进行动态更新,切记在项目使用规范中,要给索引创建别名,然后用项目中通过索引别名操作数据,而不是直接使用原索引!
创建样例数据索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PUT project_test { "settings": { "refresh_interval": "5s", "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "dynamic": false, "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }
为该索引创建别名
1 2 3 4 5 6 7 8 9 10 11 POST _aliases { "actions": [ { "add": { "index": "project_test", "alias": "project_test_alias" } } ] }
此时我们就可以使用project_test_alias这个别名在项目中操作使用
1 2 3 4 5 6 7 8 POST project_test_alias/_create/1 {"content":"我想,若非身不由己,或者走投无路,没有人会愿意走上这条“Green mile”之路的。然而,当我在电影中看到:一个能行上帝神迹的人,最终选择了走上这条道路归回天家的时候,我的心震撼了。震撼的不是上帝神迹的自我毁灭,而是他做出这般选择的理由如此充分!"} POST project_test_alias/_create/2 {"content":"可是,拯救的工作,是一项多么沉重和艰辛的负担啊"} POST project_test_alias/_create/3 {"content":"可怜的戴尔,可怜的戴尔,我在这里感觉到了。他终于解脱了,他很幸运。无论过程如何,戴尔算是幸运的了……"}
目前只有content字段,后续需要增加一个字段且需要被索引,我们可以用原索引创建一个数据拷贝。此时就可以用到reindex, _reindex会将一个索引的数据copy到另一个索引,默认情况下存在相同的_id会进行覆盖(一般不会发生,除非是将两个索引的数据copy到一个索引中),可以使用以下命令将索引快照进行copy:
1.先创建新索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PUT project_test_v2 { "settings": { "refresh_interval": "5s", "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "dynamic": false, "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" }, "title": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }
2.使用reindex将原索引数据复制到新索引中
1 2 3 4 5 6 7 8 9 POST _reindex { "source": { "index": "project_test" }, "dest": { "index": "project_test_v2" } }
至此原索引数据已复制到新索引中,此时就需要将原来的别名指向修改到新的索引即可完成索引重建,将所有删除和增加放在一个API中操作,减少替换时间带来的影响
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 POST _aliases { "actions": [ { "remove": { "index": "project_test", "alias": "project_test_alias" } }, { "add": { "index": "project_test_v2", "alias": "project_test_alias" } } ] }
remote远程reindex到本地
注意此时需要关注网络带宽,避免阻塞,可以将size参数调小来调控reindex速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST _reindex { "source": { "remote": { "host": "http://192.168.44.143:9200", "username": "elastic", "password": "elastic" }, "index": "source", "size": 100 }, "dest": { "index": "dest" } }
加快reindex速度
提高reindex的批次size,默认是1000,此时可以适当提高size来增加速度
1 2 3 4 5 6 7 8 9 10 POST _reindex { "source": { "index": "project_test", "size": 5000 }, "dest": { "index": "project_test_v2" } }
通过slied参数增加reindex并发,建议不要超过索引的分片数,因为有可能适得其反
1 2 3 4 5 6 7 8 9 10 POST _reindex?slices=5&refresh { "source": { "index": "project_test", "size": 5000 }, "dest": { "index": "project_test_v2" } }
将副本数设置为0,在创建新索引时将number_of_replicas设置为0,等后面数据重建完成后再修改副本数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PUT project_test_v2 { "settings": { "refresh_interval": "-1", "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "dynamic": false, "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" }, "title": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }
关闭或增加refresh间隔,索引默认refresh时间为1s,修改为-1即为禁用,或者设置为30s以上,减少refresh频次。切记reindex数据完成后,不要忘了将此数值改回1s。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PUT project_test_v2 { "settings": { "refresh_interval": "-1", "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "dynamic": false, "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" }, "title": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }
对于大数据量的索引进行reindex,建议加上 wait_for_completeion=false参数条件,这样执行reindex任务时将直接返回taskid,而不是一直夯着等到完成
1 2 3 4 5 6 7 8 9 10 11 12 POST _reindex?wait_for_completeion=false { "source": { "index": "project_test" }, "dest": { "index": "project_test_v2" } } # 可以通过以下API获取reindex任务进度 GET _task?detailed=true&actions=*reindex