前言
相信使用过elasticsearch的同学都知道,ES能给我们的搜索带来巨大的性能提升,使用起来也很简单方便,可以通过springboot的集成,直接用repository来保存数据,查询数据,方便至极,也可以使用ElasticsearchTemplate模板类来调用api,coding人相对来说会比较简单,但是前期的设计需要认真思考,更多的是结合当前的业务场景以及将来可能要做的场景来创建每一个doc,而doc中的mapping可以通过java bean添加注解的方式来创建,也可以手动去创建。当我们创建好mapping之后,是不可以更改的,比如想把type=text来改成type=keyword, 因为text是要对此属性进行分词,不能对属性进行"聚合"(聚合时可能是通过分词之后的结果进行分词), keyword是不对属性进行分词的。如果想从最初的type=text改成type=keyword,该如何去做呢?特别当数据量非常大的时候(最好前期考虑周到一些,后期可以避免一些不必要的问题)将是痛苦的过程,不可能数据全部重新洗一遍吧(DB-->ES), 那肯定会累死你, 下面说一下我是如何做的?
第一步查看索引对应的settings
curl ip:port/index/_settings?pretty
{
"index" : {
"settings" : {
"index" : {
"refresh_interval" : "1s",
"number_of_shards" : "5",
"provided_name" : "index",
"creation_date" : "1568094284623",
"store" : {
"type" : "fs"
},
"number_of_replicas" : "1",
"uuid" : "eZL-wKXERcGJB-Ek0iqLkw",
"version" : {
"created" : "5061099"
}
}
}
}
}
创建的每个索引默认的刷新间隔是1s, 副本分片个数为1
第二步设置索引的刷新间隔为-1, 即不刷新
curl -XPUT ip:port/index/_settings -d ' { "number_of_replicas": 0 }'
第三步设置索引的副本分片个数为0,即在同步数据时,只需要同步到主分片(可以提升性能,不用同步至副本分片)
curl -XPUT ip:port/index/_settings -d ' {"refresh_interval": -1}'
第四步确认属性修改成功
{
"index" : {
"settings" : {
"index" : {
"refresh_interval" : "-1",
"number_of_shards" : "5",
"provided_name" : "index",
"creation_date" : "1568094284623",
"store" : {
"type" : "fs"
},
"number_of_replicas" : "0",
"uuid" : "eZL-wKXERcGJB-Ek0iqLkw",
"version" : {
"created" : "5061099"
}
}
}
}
}
第五步开始重新reindex,即把旧索引的数据同步至新索引
curl -XPOST ip:port/_reindex -d '
{
"source": {
"index": "index_old",
"size": 5000 #批量同步数据量
},
"dest": {
"index": "index_new"
}
}'
当然如果数据量很大时,此步骤时间会很长,耐心等待即可
最后一步,修改刷新间隔和副本分片数据为原始数据
curl -XPUT ip:port/index/_settings -d '
{
"refresh_interval": "1s",
"number_of_replicas": 1
}'
然后把旧索引给干掉,使用新索引即可
扩展:
上面的方式可以通过reindex的方式把旧数据重新copy一份到新索引,那么此时需要修改线上的代码,把其索引指定到新索引,再重新发布,有没有办法线上不停机然后还能把索引切换到新索引呢?
方法当然有,请看如下骚操作:
第一步,先给旧索引创建一个别名
两种方法:
第一种:curl -XPUT ip:port/old_index/_alias/index_alias
第二种:
curl -XPOST ip:port/_aliases
{
"actions": [
{
"add": {
"index": "index_old",
"alias": "index_alias"
}
}
]
}
那么此时我们再代码中可以使用index_alias这个所以名称来操作索引index_old了,前期的时候其实大家就应该把别名给创建好,代码中尽量都使用别名,而不是直接使用索引名
第二步,此时要切旧索引指向的别名为新索引指向别名
curl -XPOST ip:port/_aliases
{
"actions": [
{
"remove": {
"index": "old_index",
"alias": "alias_index"
},
"add": {
"index": "new_index",
"alias": "alias_index"
}
}
]
}
然后大功告成