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>

這樣就可以在後臺重新索引了所有數據,而沒有任何停機時間。


分享到:


相關文章: