ElasticSearch-生命週期管理

誰主沉浮oo7發表於2020-08-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)組成,比如bookpeople都可以用作索引名稱,可以簡單類比為關係型資料庫的表(table)。

所謂生命,即;索引的生與死便是建立刪除了。

在我們日常使用 Elasticsearch 的時候,索引的建立與刪除似乎是很簡單的事情,用的時候便建立,不用了刪除即可,有什麼好管理的呢?

這就要從 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 等也會經過相同的一個生命週期。

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 的時間為準。
  • Warm Phase
    • Allocate 設定副本數、修改分片分配規則(如將分片遷移到中等配置的節點上)等
    • Read-Onlly 設定當前索引為只讀狀態
    • Force Merge 合併 segment 操作
    • Shrink 縮小 shard 分片數
  • Cold Phase
    • Allocate 同上
  • Delete Phase
    • Delete 刪除
      從上面看下來整體操作還是很簡單的,Kibana 也提供了一套 UI 介面來設定這些策略,如下所示:

      從上圖看下來 ILM 的設定是不是一目瞭然呢?

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

相關文章