ElasticSearch-生命周期管理
- 2020 年 8 月 24 日
- 筆記
1月29日,Elastic Stack 迎來 6.6 版本的發布,該版本帶來很多新功能,比如:
- Index Lifecycle Management
- Frozen Index
- Geoshape based on Bkd Tree
- SQL adds support for Date histograms
- ……
在這些眾多功能中,Index Lifecycle Management(索引生命周期管理,後文簡稱 ILM) 是最受社區歡迎的。今天我們從以下幾方面來快速了解下該功能:
- 為什麼索引會有生命?什麼是索引生命周期?
- ILM 是如何劃分索引生命周期的?
- ILM 是如何管理索引生命周期的?
- 實戰
Index Lifecycle 索引生命周期
先來看第一個問題:
為什麼索引有生命?
索引(Index)是 Elasticsearch 中數據組織的一個邏輯概念,是具有相同或相似欄位的文檔組合。它由眾多分片(Shard)組成,比如book
、people
都可以用作索引名稱,可以簡單類比為關係型資料庫的表(table)。
所謂生命,即生
與死
;索引的生與死便是創建
與刪除
了。
在我們日常使用 Elasticsearch 的時候,索引的創建與刪除似乎是很簡單的事情,用的時候便創建,不用了刪除即可,有什麼好管理的呢?
這就要從 Elasticsearch 的應用場景來看了。
在業務搜索
場景,用戶會將業務數據存儲在 Elasticsearch 中,比如商品數據、訂單數據、用戶數據等,實現快速的全文檢索功能。像這類數據基本都是累加的,不會刪除。一般刪除的話,要麼是業務升級,要麼是業務歇菜了。此種場景下,基本只有生,沒有死,也就不存在管理一說。
而在日誌業務
場景中,用戶會將各種日誌,如系統、防火牆、中間件、資料庫、web 伺服器、應用日誌等全部實時地存入 Elasticsearch 中,進行即時日誌查詢與分析。這種類型的數據都會有時間維度,也就是時序性的數據。由於日誌的數據量過大,用戶一般不會存儲全量的數據,一般會在 Elasticsearch 中存儲熱數據,比如最近7天、30天的數據等,而在7天或者30天之前的數據都會被刪除
。為了便於操作,用戶一般會按照日期來建立索引,比如 nginx 的日誌索引名可能為 nginx_log-2018.11.12
、nginx_log-2018.11.13
等,當要查詢或刪除某一天的日誌時,只需要針對對應日期的索引做操作就可以了。那麼在該場景下,每天都會上演大量索引的生與死。
一個索引由生到死的過程,即為一個生命周期。舉例如下:
生:在 2019年2月5日
創建 nginx_log-2019.02.05
的索引,開始處理日誌數據的讀寫請求
生:在 2019年2月6日
nginx_log-2019.02.05
索引便不再處理寫請求,只處理讀請求
死:在 2019年3月5日
刪除 nginx_log-2018.02.05
的索引
其他的索引,如 nginx_log-2019.02.06
等也會經過相同的一個生命周期。
ILM 是如何劃分索引生命周期的?
我們現在已經了解何為生命周期了,而最簡單的生命周期只需要生與死兩個階段即可。但在實際使用中生命周期是有多個階段的,我們來看下 ILM 是如何劃分生命周期的。
ILM 一共將索引生命周期分為四個階段(Phase):
- Hot 階段
- Warm 階段
- Cold 階段
- Delete 階段
如果我們拿一個人的生命周期來做類比的話,大概如下圖所示:
Hot 階段
索引數據正在活躍的更新和查詢
Hot 階段可類比為人類嬰兒到青年
的階段,在這個階段,它會不斷地進行知識的輸入與輸出(數據讀寫),不斷地長高長大(數據量增加)成有用的青年。
由於該階段需要進行大量的數據讀寫,因此需要高配置的節點,一般建議將節點記憶體與磁碟比
控制在 32 左右,比如 64GB 記憶體搭配 2TB 的 SSD
硬碟。
Warm 階段
索引數據不再被更新,但是仍被查詢
Warm 階段可類比為人類青年到中年
的階段,在這個階段,它基本不會再進行知識的輸入(數據寫入),主要進行知識輸出(數據讀取),為社會貢獻價值。
由於該階段主要負責數據的讀取,中等配置的節點即可滿足需求,可以將節點記憶體與磁碟比
提高到 64~96 之間,比如 64GB 記憶體搭配 4~6TB 的 HDD
磁碟。
Cold 階段
索引已經不被更新且很少查詢。但是索引數據的資訊還需要被搜索,若被搜索則比較慢
Cold 階段可類別比為人類中年到老年
的階段,在這個階段,它退休了,在社會有需要的時候才出來輸出下知識(數據讀取),大部分情況都是靜靜地待著。
由於該階段只負責少量的數據讀取工作,低等配置的節點即可滿足要求,可以將節點記憶體與磁碟比
進一步提高到 96 以上,比如128,即 64GB 記憶體搭配 8 TB 的 HDD
磁碟。
Delete 階段
索引不再被需要可以安全的刪除
Delete 階段可類比為人類壽終正寢
的階段,在發光發熱之後,靜靜地逝去,Rest in Peace~
ILM 對於索引的生命周期進行了非常詳細的劃分,但它並不強制要求必須有這個4個階段,用戶可以根據自己的需求組合成自己的生命周期。
ILM 是如何管理索引生命周期的?
所謂生命周期的管理就是控制 4 個生命階段轉換,何時由 Hot 轉為 Warm,何時由 Warm 轉為 Cold,何時 Delete 等。
階段的轉換必然是需要時機的,而對於時序數據來說,時間必然是最好的維度,而 ILM 也是以時間為轉換的衡量單位。比如下面這張轉換的示意圖,即默認是 Hot 階段,在索引創建 3 天后轉為 Warm 階段,7 天后轉為 Cold 階段,30 天后刪除。這個設置的相關欄位為 min_age
,後文會詳細講解。
ILM 將不同的生命周期管理策略稱為 Policy
,而所謂的 Policy
是由不同階段(Phase
)的不同動作(Action
)組成的。
Action是一系列操作索引的動作,比如 Rollover、Shrink、Force Merge等,不同階段可用的 Action 不同,詳情如下:
- Hot Phase
- Rollover
滾動索引操作,可用在索引大小或者文檔數達到某設定值時,創建新的索引用於數據讀寫,從而控制單個索引的大小。這裡要注意的一點是,如果啟用了 Rollover,那麼所有階段的時間不再以索引創建時間為準,而是以該索引 Rollover 的時間為準。
- Rollover
- Warm Phase
- Allocate 設定副本數、修改分片分配規則(如將分片遷移到中等配置的節點上)等
- Read-Onlly 設定當前索引為只讀狀態
- Force Merge 合併 segment 操作
- Shrink 縮小 shard 分片數
- Cold Phase
- Allocate 同上
- Delete Phase
- Delete 刪除
從上面看下來整體操作還是很簡單的,Kibana 也提供了一套 UI 介面來設置這些策略,如下所示:
從上圖看下來 ILM 的設置是不是一目了然呢?
- Delete 刪除
當然,ILM 是有自己的 api 的,比如上面圖片對應的 api 請求如下:
PUT /_ilm/policy/test_ilm2
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_age": "30d",
"max_size": "50gb"
}
}
},
"warm": {
"min_age": "3d",
"actions": {
"allocate": {
"require": {
"box_type": "warm"
},
"number_of_replicas": 0
},
"forcemerge": {
"max_num_segments": 1
},
"shrink": {
"number_of_shards": 1
}
}
},
"cold": {
"min_age": "7d",
"actions": {
"allocate": {
"require": {
"box_type": "cold"
}
}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
這裡不展開講了,感興趣的同學可以自行查看官方手冊。
現在管理策略(Policy)已經有了,那麼如何應用到索引(Index)上面呢?
方法為設定如下的索引配置:
index.lifecycle.name 設定 Policy 名稱,比如上面的 test_ilm2
index.lifecycle.rollover_alias 如果使用了 Rollover,那麼還需要指定該別名
修改索引配置可以直接修改(PUT index_name/_settings
)或者通過索引模板(Index Template
)來實現。
我們這裡不展開講了,大家參考下面的實戰就明白了。
實戰
目標
現在需要收集 nginx 日誌,只需保留最近30天
的日誌,但要保證最近7天
的日誌有良好的查詢性能,搜索響應時間在 100ms
以內。
為了讓大家可以快速看到效果,下面實際操作的時候會將 30天
、7天
替換為 40秒
、20秒
。
ES 集群架構
這裡我們簡單介紹下這次實戰所用 ES 集群的構成。該 ES 集群一共有 3個節點組成,每個節點都有名為 box_type 的屬性,如下所示:
GET _cat/nodeattrs?s=attr
es01_hot 172.24.0.5 172.24.0.5 box_type hot
es02_warm 172.24.0.4 172.24.0.4 box_type warm
es03_cold 172.24.0.3 172.24.0.3 box_type cold
由上可見我們有 1 個 hot 節點、1 個 warm 節點、1 個 cold 節點,分別用於對應 ILM 的階段,即 Hot 階段的索引都位於 hot 上,Warm 階段的索引都位於 warm 上,Cold 階段的索引都位於 cold 上。
創建 ILM Policy
根據要求,我們的 Policy 設定如下:
- 索引名以 nginx_logs 為前綴,且以每10個文檔做一次 Rollover
- Rollover 後 5 秒轉為 Warm 階段
- Rollover 後 20 秒轉為 Cold 階段
- Rollover 後 40 秒刪除
API 請求如下:
PUT /_ilm/policy/nginx_ilm_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_docs": "10"
}
}
},
"warm": {
"min_age": "5s",
"actions": {
"allocate": {
"include": {
"box_type": "warm"
}
}
}
},
"cold": {
"min_age": "20s",
"actions": {
"allocate": {
"include": {
"box_type": "cold"
}
}
}
},
"delete": {
"min_age": "40s",
"actions": {
"delete": {}
}
}
}
}
}
創建 Index Template
我們基於索引模板來創建所需的索引,如下所示:
PUT /_template/nginx_ilm_template
{
"index_patterns": ["nginx_logs-*"],
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"index.lifecycle.name": "nginx_ilm_policy",
"index.lifecycle.rollover_alias": "nginx_logs",
"index.routing.allocation.include.box_type": "hot"
}
}
上述配置解釋如下:
- index.lifecycle.name 指明該索引應用的 ILM Policy
- index.lifecycle.rollover_alias 指明在 Rollover 的時候使用的 alias
- index.routing.allocation.include.box_type 指明新建的索引都分配在 hot 節點上
創建初始索引 Index
ILM 的第一個索引需要我們手動來創建,另外啟動 Rollover 必須以數值類型結尾,比如 nginx_logs-000001
。索引創建的 api 如下:
PUT nginx_logs-000001
{
"aliases": {
"nginx_logs": {
"is_write_index":true
}
}
}
此時索引分布如下所示:
修改 ILM Polling Interval
ILM Service 會在後台輪詢執行 Policy,默認間隔時間為 10 分鐘,為了更快地看到效果,我們將其修改為 1 秒。
PUT _cluster/settings
{
"persistent": {
"indices.lifecycle.poll_interval":"1s"
}
}
開始吧
一切準備就緒,我們開始吧!
首先執行下面的新建文檔操作 10 次。
POST nginx_logs/_doc
{
"name":"abbc"
}
之後 Rollover 執行,新的索引創建,如下所示:
5 秒後,nginx_logs-000001
轉到 Warm 階段
15 秒後(20 秒是指距離 Rollover 的時間,因為上面已經過去5秒了,所以這裡只需要15秒),nginx_logs-00001
轉到 Cold 階段
25 秒後,nginx_logs-00001
刪除
至此,一個完整的 ILM Policy 執行的流程就結束了,而後續 nginx_logs-000002
也會按照這個設定進行流轉。
總結
ILM 是 Elastic 團隊將多年 Elasticsearch 在日誌場景領域的最佳實踐進行的一次總結歸納和落地實施,極大地降低了用好 Elasticsearch 的門檻。掌握了 ILM 的核心概念,也就意味著掌握了 Elasticsearch 的最佳實踐。希望本文能對大家入門 ILM 有所幫助。
結語
歡迎關注微信公眾號『碼仔zonE』,專註於分享Java、雲計算相關內容,包括SpringBoot、SpringCloud、微服務、Docker、Kubernetes、Python等領域相關技術乾貨,期待與您相遇!