1. 程式人生 > >[Elasticsearch] 索引管理 (五)

[Elasticsearch] 索引管理 (五)

預設對映(Default Mapping)

一般情況下,索引中的所有型別都會有相似的欄位和設定。因此將這些常用設定在_default對映中指定會更加方便,這樣就不需要在每次建立新型別的時候都重複設定。_default對映的角色是新型別的模板。所有在_default對映之後建立的型別都會包含所有的預設設定,除非顯式地在型別對映中進行覆蓋。

比如,我們使用_default對映對所有型別禁用_all欄位,唯獨對blog型別啟用它。可以這樣實現:

PUT /my_index
{
    "mappings": {
        "_default_": {
            "_all"
: { "enabled": false } }, "blog": { "_all": { "enabled": true } } } }

資料重索引

雖然你可以向索引中新增新的型別,或者像型別中新增新的欄位,但是你不能新增新的解析器或者對現有欄位進行修改。如果你這麼做了,就會讓已經索引的資料變的不正確,導致搜尋不能正常的進行。

為已經存在的資料適用這些更改的最簡單的方法就是重索引(Reindex):新建一個擁有最新配置的索引,然後將所有舊索引中的資料拷貝到新的索引中。

_source欄位的一個優勢是在ES中你已經擁有了整個文件。你不需要通過資料庫來重建你的索引,這種方法通常會更慢。

為了從舊索引中高效地對所有文件進行重索引,可以使用scan和scroll來批量地從舊索引中獲取文件,然後使用bulk API將它們新增到新索引中。

批量重索引

你可以同時執行多個重索引任務,但是你顯然不想要它們的結果有任何重疊。可以根據date或者timestamp欄位對重索引的任務進行劃分,成為規模較小的任務:

GET /old_index/_search?search_type=scan&scroll=1m
{
    "query": {
        "range": {
            "date": {
                "gte":  "2014-01-01"
, "lt": "2014-02-01" } } }, "size": 1000 }

如果你正在持續地更改舊索引中的資料,想必你也希望這些更改也會被反映到新索引中。這可以通過再次執行重索引任務來完成,但是還是可以通過對日期欄位進行過濾來得到在上次重索引開始後才被新增的文件。


索引別名和零停機時間(Index Alias and Zero Downtime)

重索引的問題在於你需要更新你的應用讓它使用新的索引名。而索引別名可以解決這個問題。

一個索引別名就好比一個快捷方式(Shortcut)或一個符號連結(Symbolic Link),索引別名可以指向一個或者多個索引,可以在任何需要索引名的API中使用。使用別名可以給我們非常多的靈活性。它能夠讓我們:

  • 在一個執行的叢集中透明地從一個索引切換到另一個索引
  • 讓多個索引形成一個組,比如last_three_months
  • 為一個索引中的一部分文件建立一個檢視(View)

我們會在本書的後面討論更多關於別名的其它用途。現在我們要解釋的是如何在零停機時間的前提下,使用別名來完成從舊索引切換到新索引。

有兩個用來管理別名的端點(Endpoint):_alias用來完成單一操作,_aliases用來原子地完成多個操作。

在這個場景中,我們假設你的應用正在使用一個名為my_index的索引。實際上,my_index是一個別名,它指向了當前正在使用的真實索引。我們會在真實索引的名字中包含一個版本號碼:my_index_v1my_index_v2等。

首先,建立索引my_index_v1,然後讓別名my_index指向它:

PUT /my_index_v1 
PUT /my_index_v1/_alias/my_index 

可以通過下面的請求得到別名指向的索引:

GET /*/_alias/my_index

或者查詢指向真實索引的有哪些別名:

GET /my_index_v1/_alias/*

它們都會返回:

{
    "my_index_v1" : {
        "aliases" : {
            "my_index" : { }
        }
    }
}

然後,我們決定要為索引中的一個欄位更改其對映。當然,我們是不能修改當前的對映的,因此我們只好對資料進行重索引。此時我們建立了擁有新的對映的索引my_index_v2

PUT /my_index_v2
{
    "mappings": {
        "my_type": {
            "properties": {
                "tags": {
                    "type":   "string",
                    "index":  "not_analyzed"
                }
            }
        }
    }
}

緊接著,我們會根據資料重索引中的流程將my_index_v1中的資料重索引到my_index_v2。一旦我們確定了文件已經被正確地索引,我們就能夠將別名切換到新的索引上了。

一個別名能夠指向多個索引,因此當我們將別名指向新的索引時,我們還需要刪除別名原來到舊索引的指向。這個改變需要是原子的,即意味著我們需要使用_aliases端點:

POST /_aliases
{
    "actions": [
        { "remove": { "index": "my_index_v1", "alias": "my_index" }},
        { "add":    { "index": "my_index_v2", "alias": "my_index" }}
    ]
}

現在你的應用就在零停機時間的前提下,實現了舊索引到新索引的透明切換。

TIP

即使你認為當前的索引設計是完美的,將來你也會發現有一些部分需要被改變,而那個時候你的索引已經在生產環境中被使用了。

在應用中使用索引別名而不是索引的真實名稱,這樣你就能夠在任何需要的時候執行重索引操作。應該充分地使用別名。