0停机情况下修改Elasticsearch mapping

使用ElasticSearch 作为搜索模型时有一个很大问题是,每当更改架构时都必须重新编制索引。数据集很大时需要很长的时间,这给我们带来了很多停机时间。对于大多数应用程序来说太多了。

本文将介绍如何在0停机情况下修改Elasticsearch mapping


问题: 为什么不能修改已存在数据的字段类型?


为了使您的数据可搜索,数据库需要知道每个字段包含什么类型的数据以及应如何对其进行索引。如果将字段类型从a切换string为a date,那么已经为该字段建立索引的所有数据将变得无用。所以您需要重新索引该字段。

这不仅适用于Elasticsearch,而且适用于使用索引进行搜索的任何数据库。而且,如果不使用索引,则会牺牲查询速度。

Elasticsearch(和Lucene)将其索引存储在不可变的段中  -每个段都是一个“微型”反向索引。这些字段永远不会更新。更新文档实际上会创建一个新文档并将旧文档标记为已删除。文档(或更新现有文档),创建新的段,并在后台运行合并过程,将几个较小的字段合并为一个新的大字段,然后将旧字段完全删除。

通常,Elasticsearch中的索引将包含不同类型的文档。每个_type都有自己的模式或映射。一个段可以包含任何类型的文档。因此,如果要更改单个类型中单个字段的字段定义,除了重新索引索引中的所有文档外,别无选择。

Elasticsearch如何修改Mapping


1.添加字段,可以使用elasticsearch 的添加字段api添加字段, 这种情况下无需reindex:

将新字段添加到现有索引或更改现有字段的搜索设置。

<code>PUT /twitter/_mapping
{
"properties": {
"email": {
"type": "keyword"
}
}
}/<code>

2.使用_reindex api将文档复制已定义好Mapping的index中

<code>curl -XPOST localhost:9200/_reindex?pretty -d'{
"source": {
"index": "src"
},
"dest": {
"index": "dest"
}
}/<code>

在不停机的状态下更新Mapping

索引别名(alias) 使我们能够灵活地在后台重新索引数据,一个别名就像一个符号链接可以指向一个或多个真实索引(Index)。

典型的工作流程如下。首先,创建一个索引,在名称后附加一个版本或时间戳:

<code>curl -XPUT localhost:9200/my_index_v1 -H 'Content-Type: application/json' -d '
{ ... mappings ... }/<code>

创建一个指向索引的别名:

<code>curl -XPOST localhost:9200/_aliases -H 'Content-Type: application/json' -d '
{
"actions": [
{ "add": {
"alias": "my_index",
"index": "my_index_v1"
}}
]
}
/<code>

现在,您的应用程序可以像真实索引一样使用my_index

需要重新索引数据时,可以创建新索引,并附加新的版本号:

<code>curl -XPUT localhost:9200/my_index_v2 -H 'Content-Type: application/json' -d '
{ ... mappings ... }/<code>

将数据从重新索引,my_index_v1到new my_index_v2 (参考上面reindex内容),然后更改myindex别名以指向新索引:

<code>curl -XPOST localhost:9200/_aliases -H 'Content-Type: application/json' -d '
{
"actions": [
{ "remove": {
"alias": "my_index",
"index": "my_index_v1"
}},
{ "add": {
"alias": "my_index",
"index": "my_index_v2"
}}
]
}
/<code>

最后,删除旧索引:

<code>curl - XDELETE本地主机:9200 / my_index_v1/<code>

这样就可以在后台重新索引了所有数据,而没有任何停机时间。


分享到:


相關文章: