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等領域相關技術乾貨,期待與您相遇!