【elasticsearch】——用ILM策略自動完成冷熱資料分離【轉】
原文連結:https://blog.csdn.net/weixin_40449300/article/details/106034912
一、前言
從Elastic Stack 迎來 6.6 版本後,就增加了ILM生命週期管理的功能。下面我們從以下幾個方面來分析:
- 為什麼索引會有生命?什麼是索引生命週期?
- ILM 是如何劃分索引生命週期的?
- ILM 是如何管理索引生命週期的?
二、回答問題
問題1:為什麼索引有生命?
答:這就要從 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
等也會經過相同的一個生命週期。
問題2:ILM 是如何劃分索引生命週期的?
答:ILM 一共將索引生命週期分為四個階段(Phase):
- Hot 階段
- Warm 階段
- Cold 階段
- Delete 階段
問題3.: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 的時間為準。
- Warm Phase
- Allocate 設定副本數、修改分片分配規則(如將分片遷移到中等配置的節點上)等
- Read-Onlly 設定當前索引為只讀狀態
- Force Merge 合併 segment 操作
- Shrink 縮小 shard 分片數
- Cold Phase
- Allocate 同上
- Delete Phase
- Delete 刪除
三、實戰
1、目標
現在需要收集 nginx 日誌,只需保留最近30天
的日誌,但要保證最近7天
的日誌有良好的查詢效能,搜尋響應時間在100ms
以內。
為了讓大家可以快速看到效果,下面實際操作的時候會將30天
、7天
替換為40秒
、20秒
。
2、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 上。
3、建立 ILM Policy
根據要求,我們的 Policy 設定如下:
- 索引名以 nginx_logs 為字首,且以每10個文件做一次 Rollover
- Rollover 後 5 秒轉為 Warm 階段
- Rollover 後 20 秒轉為 Cold 階段
- Rollover 後 40 秒刪除
#建立ILM curl -XPUT "localhost:9200/_ilm/policy/nginx_ilm_policy" -H 'Content-Type: application/json' -d' { "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": {} } } } } } '
4、建立 Index Template
我們基於索引模板來建立所需的索引,如下所示:
#建立模板,關聯索引和ILM策略 curl -XPUT "localhost:9200/_template/nginx_ilm_template" -H 'Content-Type: application/json' -d' { "index_patterns": ["nginx_logs-*"], "settings": { "number_of_shards": 5, "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 節點上
5、建立初始索引 Index
ILM 的第一個索引需要我們手動來建立,另外啟動 Rollover 必須以數值型別結尾,比如nginx_logs-000001
。索引建立的 api 如下:
#建立索引 curl -XPUT "localhost:9200/nginx_logs-000001" -H 'Content-Type: application/json' -d' { "aliases": { "nginx_logs": { "is_write_index":true } } }
6、修改 ILM Polling Interval
ILM Service 會在後臺輪詢執行 Policy,預設間隔時間為 10 分鐘,為了更快地看到效果,我們將其修改為 1 秒。
#修改輪詢時間,ILM Service 會在後臺輪詢執行 Policy,預設間隔時間為 10 分鐘,為了更快地看到效果,我們將其修改為 1 秒。 curl -XPUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d' { "persistent": { "indices.lifecycle.poll_interval":"1s" } } '
7、批量寫入資料
程式碼:https://github.com/oliver006/elasticsearch-test-data
#寫入資料,必須通過別名寫入 $ python es_data_gen.py --es_url=http://172.16.105.4:9200 --index_name=nginx_logs --num_of_shards=5 --num_of_replicas=0 --count=10000 [I 200510 13:26:15 es_data_gen:52] Trying to create index http://172.16.105.4:9200/nginx_logs [I 200510 13:26:15 es_data_gen:57] Looks like the index exists already [I 200510 13:26:15 es_data_gen:226] Generating 10000 docs, upload batch size is 1000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 360ms, total docs uploaded: 1000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 7ms, total docs uploaded: 2000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 3000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 4000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 7ms, total docs uploaded: 5000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 6000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 7000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 8000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 9000 [I 200510 13:26:16 es_data_gen:78] Upload: OK - upload took: 6ms, total docs uploaded: 10000 [I 200510 13:26:16 es_data_gen:259] Done - total docs uploaded: 10000, took 1 seconds #觀察資料流轉 $ curl localhost:9200/_cat/shards nginx_logs-000002 4 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 1 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 2 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 3 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 0 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000001 4 p STARTED 2053 215kb 172.16.105.13 node-2 nginx_logs-000001 1 p STARTED 2014 211.8kb 172.16.105.13 node-2 nginx_logs-000001 2 p STARTED 1982 208.7kb 172.16.105.13 node-2 nginx_logs-000001 3 p STARTED 1988 208.6kb 172.16.105.13 node-2 nginx_logs-000001 0 p STARTED 1963 206.2kb 172.16.105.13 node-2 $ curl localhost:9200/_cat/shards nginx_logs-000002 4 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 1 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 2 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 3 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 0 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000001 4 p RELOCATING 2053 215kb 172.16.105.13 node-2 -> 172.16.105.5 -EhbM-T1TVOBrYcBJFHwzQ node-3 nginx_logs-000001 1 p RELOCATING 172.16.105.13 node-2 -> 172.16.105.5 -EhbM-T1TVOBrYcBJFHwzQ node-3 nginx_logs-000001 2 p STARTED 172.16.105.13 node-2 nginx_logs-000001 3 p STARTED 1988 208.6kb 172.16.105.13 node-2 nginx_logs-000001 0 p STARTED 1963 206.2kb 172.16.105.13 node-2 #生命週期結束,建立了新的索引名字,原來的經過流轉已經被刪除了 $ curl localhost:9200/_cat/shards nginx_logs-000002 4 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 1 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 2 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 3 p STARTED 0 230b 172.16.105.4 node-1 nginx_logs-000002 0 p STARTED 0 230b 172.16.105.4 node-1 #清楚測試環境資料 $ curl -XDELETE localhost:9200/nginx* && curl -XDELETE localhost:9200/_template/nginx_ilm_template && curl -XDELETE localhost:9200/_ilm/policy/nginx_ilm_policy