1. 程式人生 > 實用技巧 >【elasticsearch】——用ILM策略自動完成冷熱資料分離【轉】

【elasticsearch】——用ILM策略自動完成冷熱資料分離【轉】

原文連結:https://blog.csdn.net/weixin_40449300/article/details/106034912

一、前言

從Elastic Stack 迎來 6.6 版本後,就增加了ILM生命週期管理的功能。下面我們從以下幾個方面來分析:

  1. 為什麼索引會有生命?什麼是索引生命週期?
  2. ILM 是如何劃分索引生命週期的?
  3. ILM 是如何管理索引生命週期的?

二、回答問題

問題1:為什麼索引有生命?

答:這就要從 Elasticsearch 的應用場景來看了。

業務搜尋場景,使用者會將業務資料儲存在 Elasticsearch 中,比如商品資料、訂單資料、使用者資料等,實現快速的全文檢索功能。像這類資料基本都是累加的,不會刪除。一般刪除的話,要麼是業務升級,要麼是業務歇菜了。此種場景下,基本只有生,沒有死,也就不存在管理一說。

而在日誌業務場景中,使用者會將各種日誌,如系統、防火牆、中介軟體、資料庫、web 伺服器、應用日誌等全部實時地存入 Elasticsearch 中,進行即席日誌查詢與分析。這種型別的資料都會有時間維度,也就是時序性的資料。由於日誌的資料量過大,使用者一般不會儲存全量的資料,一般會在 Elasticsearch 中儲存熱資料,比如最近7天、30天的資料等,而在7天或者30天之前的資料都會被刪除。為了便於操作,使用者一般會按照日期來建立索引,比如 nginx 的日誌索引名可能為nginx_log-2018.11.12nginx_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):

  1. Hot 階段
  2. Warm 階段
  3. Cold 階段
  4. 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