每一个成功人士的背后,都曾有过勇敢而孤独的决定。放弃并不难,但坚持才是真正的酷。
版本:Elasticsearch 6.4.0
一、问题
在项目中后期,如果需要调整索引的Mapping结构,例如将iksmart改为ikmax_word或增加分片数量等,而Elasticsearch不允许直接修改这些内容,应该怎么办?
常见的解决方法包括: - 根据新的Mapping结构创建一个新的索引。 - 将旧索引中的所有数据导入到新索引中。 - 告知用户业务需要暂停一段时间。 - 修改程序代码,将索引名称更改为新的索引名称,然后重新部署。 - 告知用户服务已经恢复,同时表示歉意。
这种方法的主要缺点在于:需要修改程序代码,有时还需要暂停业务的运行。
有没有更好的解决方案呢?答案是肯定的。Elasticsearch 提供了一种更好的方法,即通过索引别名来重建索引,从而不需要通知用户或修改程序代码。
二、索引别名
索引别名可以关联一个或多个索引,并在任何需要索引名称的地方使用。简单来说,别名类似于Windows的快捷方式、Linux的软链接或MySQL的视图。别名提供了很大的灵活性,可以实现以下功能: - 在运行中的集群上,透明地切换一个索引到另一个索引。 - 对多个索引进行分组。例如,按月份创建的索引,可以通过别名与最近三个月的索引关联。这样就可以通过别名查询这三个月的所有数据。如果使用得当,别名可以更好地控制查询的数据量,从而提高查询效率。
本文开头提到的问题,可以通过索引别名来解决。接下来我们将具体讲解如何操作。
三、具体操作
如何在不停机的情况下修改索引的Mapping字段类型?大致可分为三个步骤:
使用reindex操作将旧索引(dynamicdatav2)的数据完全复制到新索引(dynamicdatav5)上:
POST _reindex
{
"source": {
"index": "dynamic_data_v2"
},
"dest": {
"index": "dynamic_data_v5"
}
}
POST /_aliases
{
"actions": [
{ "remove": { "index": "dynamic_data_v2", "alias": "dynamic_data" }},
{ "add": { "index": "dynamic_data_v5", "alias": "dynamic_data" }}
]
}
DELETE dynamic_data_v2
这样我们就实现了透明化的更新,用户不会感知到任何变化。不过需要注意的是,如果数据量非常大,复制数据会花费较多时间。因此,在构建索引之前一定要仔细规划Mapping结构。
关于索引别名的更多操作,可以参考:
https://www.elastic.co/guide/en/elasticsearch/reference/6.4/indices-aliases.html
四、可以修改Mapping的特殊情况
Elasticsearch不允许修改或删除已存在的字段,这是因为其底层使用的是Lucene库,更改Mapping可能会使已建立索引的文档失效。然而,有一些特殊情况可以进行修改: - 可以向现有的Mapping结构中添加新字段。 - 可以更改现有字段的搜索设置。
POST dynamic_data_v2/_mapping/_doc
{
"properties": {
"amount": {
"type": "text"
}
}
}
PUT dynamic_data_v2/_mapping/_doc
{
"properties": {
"amount": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 10
}
}
}
}
}
PUT dynamic_data_v2/_mapping/_doc
{
"properties": {
"name": {
"properties": {
"first": {
"type": "text"
}
}
}
}
}
五、总结
索引别名是一个非常有用的工具,尤其是在项目后期索引包含大量数据时。它不仅可以让用户无感知地维护数据更新,还可以通过组合查询实现高效精准的查询。建议在使用索引别名时,确保物理索引具有不同的Mapping和数据结构,以进一步提升检索效率。
欢迎留言讨论。