1. 程式人生 > >乾貨 | Elasticsearch索引生命週期管理探索

乾貨 | Elasticsearch索引生命週期管理探索

引言

Elasticsearch上海Meetup中ebay工程師提了索引生命週期管理的概念。的確,在Demo級別的驗證階段我們資料量比較小,不太需要關注索引的生命週期,一個或幾個索引基本就能滿足需要。所以,這也會產生一種假象,認為:“Elasticsearch不就是增刪改查,毛毛雨啦”的荒誕的假象。
但是,在實戰開發的生產環境中,索引的動態模板設定、索引Mapping設定、索引分片數/副本數設定、索引建立、開啟、關閉、刪除的全生命週期的管理必須高度關注,做好提前知識儲備,
否則,會在開發後期出現由於資料激增暴露架構設計不合理問題,甚至引發分片/節點資料丟失、叢集宕機等嚴重問題。

1、什麼是Elasticsearch索引生命週期管理?

Elasticsearch索引生命週期管理指:Elasticsearch從設定、建立、開啟、關閉、刪除的全生命週期過程的管理。
Elasticsearch生產環境中一般採用多索引結合基於時間、基於空間的橫向擴充套件的方式儲存資料,隨著資料量的增多,不用修改索引的底層架構邏輯。

2、索引生命週期管理為什麼重要?

索引管理決定Elasticsearch魯棒性、高可用性。
索引管理和搜尋、插入效能也密切相關。
實際場景例子:100節點的叢集中某一個節點資料丟失後,GET /_cat/nodes?v 介面的返回時延時延非常大,接近5-8s。搜尋、聚合的效能更不必說。
原因:節點丟失後,ES會自動複製分片到新的節點中去,但是該丟失節點的shard非常大(幾百個GB甚至上TB),叢集當時的寫入壓力也非常大。這麼大量級的資料拷貝和實時寫入,最終導致延時會非常大。

3、索引生命週期管理面臨的挑戰

1)索引管理需要ES專業知識和業務知識的結合。
業務資料多少結合業務場景,有突發情況。
2)涉及生產環境的操作。
3)使用者使用有突發情況。
比如:引數設定錯誤,分片數和副本數弄反了,路由設定錯誤。
4)索引操作的時候可能會失敗。
5)高可用性挑戰。

4、高可用的索引管理初探

Ebay的分享提及內部團隊開發了索引管理系統,會擇期分享,截止20180805 github還沒有開源,期待中。
索引生命週期管理的核心就是定義索引的早期階段,前面考慮充分了,後面的架構才會高效、穩定。
實際Elasticsearch5.X之後的版本已經推出:新增了一個Rollover API。Rollover API解決的是以日期作為索引名稱的索引大小不均衡的問題。
medcl介紹如下:Rollover API對於日誌類的資料非常有用,一般我們按天來對索引進行分割(資料量更大還能進一步拆分),沒有Rollover之前,需要在程式裡設定一個自動生成索引的模板,
相比於模板,Rollover API是更為簡潔的方式。

4.1 RollOver 的定義

當現有索引被認為太大或太舊時,滾動索引API將別名滾動到新索引。該API接受一個別名和一個條件列表。別名必須只指向一個索引。如果索引滿足指定條件,則建立一個新索引,並將別名切換到指向新索引的位置。
6.XRollover支援的三種條件是:

  • 1)索引儲存的最長時間。如: “max_age”: “7d”,
  • 2)索引支援的最大文件數。如:”max_docs”: 1000,
  • 3)索引最大磁碟空間大小。”max_size”: “5gb”。

注意:
5.X版本不支援”max_size”: “5gb”磁碟大小的方式。
分片的大小並不是一個可靠的測量標準,因為正在進行中的合併會產生大量的臨時分片大小增長,而當合並結束後這些增長會消失掉。五個主分片,每個都在合併到一個 5GB 分片的過程中,那麼此時索引大小會臨時增多 25GB!而對於文件數量來說,它的增長則是可以預測的。

4.2 RollOver的適用場景

這個特性對於存放日誌資料的場景、索引非常大、索引實時匯入資料的場景是極為友好的。
你也可以先在索引模板裡面設定索引的setting、mapping等引數, 然後設定好_rollover 規則,剩下的es會自動幫你處理。

4.3 6.XRollOverAPI呼叫方式如下:

方式一:基於序號的索引管理。

步驟1:建立索引(注意序號)

PUT /logs-000001 
{
  "aliases": {
    "logs_write": {}
  }
}

步驟2:指定RollOver規則。

POST /logs_write/_rollover 
{
  "conditions": {
    "max_age":   "7d",
    "max_docs":  2,
    "max_size":  "5gb"
  }
}

步驟3:批量插入資料。

POST logs_write/log/_bulk
{ "create": {"_id":1}}
{ "text": "111"}
{ "create": {"_id":2}}
{ "text": "222" }
{ "create": {"_id":3}}
{ "text": "333"}
{ "create": {"_id":4}}
{ "text": "4444"}

注意啦,理論上:_id=3和_id=4的資料會滾動到logs-000002的索引,實際並沒有。
這個問題困擾我一上午。
實踐驗證發現,然並卵。

步驟4:重複步驟2。
檢視返回結果如下:

{
  "old_index": "logs-000001",
  "new_index": "logs-000002",
  "rolled_over": true,
  "dry_run": false,
  "acknowledged": true,
  "shards_acknowledged": true,
  "conditions": {
    "[max_docs: 2]": true,
    "[max_age: 7d]": false,
    "[max_size: 5gb]": false
  }
}

這樣以後,後續插入的資料索引就自動變為logs-000002,logs-000003…..logs-00000N。

注意
1)執行資料插入前要先執行_rollover API。
2)_rollover API不是一勞永逸的,需要手動執行後才能生效。

方式二:基於時間的索引管理。

步驟1:建立基於日期的索引。

#PUT /<logs-{now/d}-1> with URI encoding:
PUT /%3Clogs-%7Bnow%2Fd%7D-1%3E 
{
  "aliases": {
    "logs_write": {}
  }
}

URI 編碼工具:http://tool.oschina.net/encode?type=4
輸入:<logs-{now/d}-1>
輸出:%3Clogs-%7Bnow%2Fd%7D-1%3E
這裡寫圖片描述

步驟2:插入一條資料。

PUT logs_write/_doc/1
{
  "message": "a dummy log"
}

步驟3:指定RollOver規則。

POST /logs_write/_rollover 
{
  "conditions": {
    "max_docs":   "1"
  }
}

返回結果:

{
  "old_index": "logs-2018.08.05-1",
  "new_index": "logs-2018.08.05-000002",
  "rolled_over": true,
  "dry_run": false,
  "acknowledged": true,
  "shards_acknowledged": true,
  "conditions": {
    "[max_docs: 1]": true
  }
}

注意,可能感覺到日期沒有變更困惑的問題解釋如下:
1)如果立即執行,new_index的名字就是當前的日期:logs-2018.08.05-000002。
2)如果24小時候後執行,new_index的名字就是+1天后的日期:logs-2018.08.06-000002。

5、高可用的索引管理進階

步驟1:有一個用於寫入的索引別名,其指向活躍索引(熱資料);
步驟2:另外一個用於讀取(搜尋)的索引別名,指向不活躍索引(冷資料);
步驟3:活躍索引具有和熱節點數量一樣多的分片,可以充分發揮昂貴硬體的索引寫入能力;
步驟4:當活躍索引太滿或者太老的時候,它就會滾動:新建一個索引並且索引別名自動從老索引切換到新索引;
步驟5:移動老索引到冷節點上並且縮小為一個分片,之後可以強制合併和壓縮。

具體實現,官方部落格已經做了具體的說明。
注意:

"routing.allocation.include.box_type": "hot",
"routing.allocation.total_shards_per_node": 2

單節點執行上述操作會導致失敗,具體原因待進一步驗證。

6、Rollover的不足和改進

Rollover API大大簡化了基於時間的索引的管理。但是,仍然需要以一種重複的方式呼叫_rollover API介面,可以手動呼叫,也可以通過基於crontab的工具(如director)呼叫。
但是,如果翻轉過程是隱式的並在內部進行管理,則會簡單得多。其思想是在建立索引時(或在索引模板中相等地)在別名中指定滾動條件。

PUT /<logs-{now/d}-1>
{
    "mappings": {...},
    "aliases" : {
        "logs-search" : {},
        "logs-write" : {
            "rollover" : {
                "conditions": {
                    "max_age":   "1d",
                    "max_docs":  100000
                }
            }
        }
    }
}

7、小結

  1. Elasticsearch索引生命週期管理是件大事,無論你是開發還是運維人員,千萬不要輕視。
  2. Rollover的出現能相對緩解分片、索引、叢集的壓力,相對高效的管理索引的生命週期。
  3. 結合curator的定時刪除機制會更高效。

這裡寫圖片描述
打造Elasticsearch基礎、進階、實戰第一公眾號!