天天看點

Rollover API— Elastic Stack 實戰手冊

Rollover API— Elastic Stack 實戰手冊
https://developer.aliyun.com/topic/download?id=1295 · 更多精彩内容,請下載下傳閱讀全本《Elastic Stack實戰手冊》 https://developer.aliyun.com/topic/download?id=1295 https://developer.aliyun.com/topic/es100 · 加入創作人行列,一起交流碰撞,參與技術圈年度盛事吧 https://developer.aliyun.com/topic/es100

創作人:楊松柏

了解 Elasticsearch 的同學應該都知道,索引的主分片在設定之後,改變(

shrink

split

reindex

)主分片數目的成本相當大;是以在設計之初,一定要規劃好索引的分片數目。如果叢集的中節點數目固定,且寫入的資料不會再有更新操作或者更新操作極其少;可以使用

Rollover index

的方式來限制每個索引的大小。

Rollover:

rollover-target

綁定的目前索引滿足設定的條件,執行滾動操作将會為

rollover-target

建立新索引。滾動目标可以是索引别名或者資料流;

  • 當滾動目标是别名時,執行滾動别名将指向新的索引。
  • 當滾動目标是資料流時,資料流将資料寫入到新的索引,且新索引名字尾自增 1。
POST /alias1/_rollover/my-index-000002
{
  "conditions": {
    "max_age":   "7d",
    "max_docs":  2,
    "max_size": "5gb"
  }
}           

如果需要實作 Rollover 自動化,可以自行實作一個定時任務請求該 API 或者使用 Elasticsearch 的 index lifecycle management (ILM) 功能。

API 介紹

Rollover API

POST /<rollover-target>/_rollover/<target-index>?wait_for_active_shards=<number>
POST /<rollover-target>/_rollover?wait_for_active_shards=<number>           

URI 參數

必填參數,參數類型

string

。将已存的索引别名或資料流,配置設定給目标索引,來完成執行滾動。

可選參數,參數類型

string

。代表要被建立和配置設定索引别名的目标索引名稱;

目标索引名稱必須遵循以下規則:

  1. 所有字元必須小寫
  2. 不允許包含

    \

    ,

    /

    *

    ?

    "

    <

    >

    |

    (space character)

    ,

    #

  3. 在7.0版本之前允許包含:,在7.0+不再支援
  4. 不能夠以

    -

    _

    +

    開頭
  5. 名稱不能夠是

    .

    或者

    ..

  6. 長度不能超過 255 位元組(注意:這是位元組數限制,如果是字元得看表示一個字元需要多少個位元組)
  7. 名稱以

    .

    開頭已經過時;除了隐藏索引和由插件管理的内部索引

如果

rollover-target

為資料流,

<target-index>

參數是不被允許的;執行 Rollover 資料流會按照相應規則生産新的索引:格式為

.ds-<rollover-target>-000001

,其中

-000001

,數字必為6位數,左側高位用

補充,每發生一次 Rollover 自增加1。

rollover-target

為一個索引别名,且别名綁定的索引以

-<number>

結尾;如果不指定

<target-index>

執行 Rollover ,将生成新的索引

indexName-<number>+1

如果别名現綁定的索引名稱不滿足以

-<number>

形式結尾,則必須指定

<target-index>

查詢參數

dry_run

可選參數,參數類型為

boolean

,預設值為 false。該參數的作用為檢測 index 是否滿足提供的 rollover 條件。 如果設定為true,将會完成檢查工作,但不會真正執行 rollover 。

include_type_name

boolean

,預設值為 false。在

mappings

體内要求必須有mapping type。

wait_for_active_shards

string

,預設值為 1(即隻要一個主分片處于活躍便可以執行操作)。在執行

rollover

,要求處于活躍狀态的索引分片副本數目,以保證資料的可靠和安全性;設定為

all

或任何正整數,最多為索引分片的總數(

number_of_replicas+1

)。

詳情可以參考 Active shards: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-index_.html#index-wait-for-active-shards

master_timeout

可選參數,

value

值的機關可為

d

h

m

s

ms

micros

nanos

,預設值為

30s

。 等待連接配接到主節點的時間。如果在逾時時間門檻值之前沒有收到響應,則請求失敗并傳回錯誤。

timeout

可選參數,value 值的機關可為

d

h

m

s

ms

micros

nanos

30s

。請求等待響應的時間。如果在逾時時間門檻值之前沒有收到響應,則請求失敗并傳回錯誤。

請求體參數

aliases

alias object

。包含索引的 Index aliases。詳情可以參看索引别名,批量操作的相關内容(即_aliases API)。

conditions

可選參數,參數類型

object

。如果設定條件,則隻有現有索引達到條件集任何一個條件的門檻值才會完成

rollover

。如果省略,則無條件執行

rollover

。條件集包括:

  • max_age

    d

    h

    m

    s

    ms

    micros

    nanos

    ;依據索引的建立時間與現在時間內插補點作為門檻值。
  • max_docs

    integer

    ;索引的最大文檔數目;計數不包括自上次

    refresh

    之後新添加的文檔和副本分片的文檔。
  • max_size

    可選參數, byte units 值(機關

    b

    kb

    mb

    gb

    tb

    pb

    )。索引大小的最大值,隻計算索引主分片的大小,副本不包括在内。

mappings

可選參數,參數 mapping object。為索引進行資料模組化,定義字段

schema

等。如果設定,

mapping

可能包含:

  • 字段名字(Field names)
  • 字段的資料類型(Field data types)
  • mapping中一些修飾參數(Mapping parameters)

    settings

可選參數,參數 index setting object。索引的配置選項;比如設定滾動産生的新索引副本分片數目等等。

詳情可以參看 Index Settings: https://www.elastic.co/guide/en/elasticsearch/reference/7.11/index-modules.html#index-modules-settings

Rollover的分類

依據不同

rollover target

和别名情況,可以簡單的分為三種執行情況:

别名隻綁定一個索引

rollover target

為别名,且别名和索引一對一關系;滾動請求過程如下:

  1. 建立一個新索引
  2. 給新索引添加别名
  3. 将别名與之前綁定索引的關聯關系移除

别名綁定多個索引

rollover target

為别名,且與多個索引建立了綁定關系,隻有其中一組的綁定關系

**is_write_index**

的值為

true

(如果對

**is_write_index**

有疑問,請參看索引别名小節)。在這種情況下,滾動請求過程如下:

  1. 新索引于别名的綁定時,将

    is_write_index

    設定為

    true

  2. 修改别名與舊索引的綁定關系,将

    is_write_index

    false

rollover-target 為資料流

rollover target

為資料流,滾動請求過程如下:

  1. 在資料流上添加新索引作為備份索引和寫索引
  2. 增加資料流的

    generation

    屬性

實戰示例

基礎示例

别名與索引是一對一關系,執行 _rollover 之後,别名将關聯到新的索引

PUT /logs-1  #備注1
{
  "aliases": {
    "logs_write": {}
  }
}
# Add > 2 documents to logs-1
PUT logs-1/_bulk
{"index":{}}
{"user.id":"kimchy"}
{"index":{}}
{"user.id":"tom"}

POST /logs_write/_rollover  #備注2
{
  "conditions": {
    "max_age":   "7d",
    "max_docs":  2,
    "max_size":  "5gb"
  }
}           

建立索引

logs-1

且與别名

logs_write

綁定.

logs_write

指向的索引滿足條件集中的任何一個條件(索引“年齡值”>=7天或者主分片文檔數目>=2或者主分片 size>=5gb);則

logs-000002

将會被建立,且别名

logs_write

将更新綁定到

logs-000002

如上代碼塊 Rollover API 傳回值如下

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "old_index": "logs-1",
  "new_index": "logs-000002",
  "rolled_over": true, #索引是否執行了滾動
  "dry_run": false, # 是否為 dry_run 模式
  "conditions": {  # 條件集觸發結果
    "[max_age: 7d]": false,
    "[max_docs: 2]": true,
    "[max_size: 5gb]": false,
  }
}           

通過檢視索引與别名的綁定關系,可以看到

logs_write

隻綁定

logs-000002

# 檢視指令
GET _cat/aliases/logs_write?v

#傳回值如下
alias      index       filter routing.index routing.search is_write_index
logs_write logs-000002 -      -                 

基于資料流滾動

資料流必須要提前設定一個索引模闆,否則無法建立資料流。

PUT _index_template/template
{
  "index_patterns": ["my-data-stream*"],
  "data_stream": { }
}           

建立資料流

PUT /_data_stream/my-data-stream # 備注1           

建立一個名為

my-data-stream

的資料流,并且初始化一個名字為

my-data-stream-000001

backing

索引。

檢視

GET /_data_stream/my-data-stream

。傳回值如下

{
  "data_streams" : [
    {
      "name" : "my-data-stream",
      "timestamp_field" : {
        "name" : "@timestamp"
      },
      "indices" : [
        {
          "index_name" : ".ds-my-data-stream-000001",
          "index_uuid" : "Vir6yRm4S42k8n22mZ5YBw"
        }
      ],
      "generation" : 1,
      "status" : "GREEN",
      "template" : "my-index-template",
      "ilm_policy" : "my-lifecycle-policy"
    }
  ]
}
           

插入資料,然後執行滾動

# Add > 2 documents to my-data-stream
#為了能夠實時的看到效果插入資料時,加上 refresh 參數
PUT my-data-stream/_bulk?refresh
{ "create":{ } }
{ "@timestamp": "2099-05-06T16:21:15.000Z", "message": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736" }
{ "create":{ } }
{ "@timestamp": "2099-05-06T16:25:42.000Z", "message": "192.0.2.255 - - [06/May/2099:16:25:42 +0000] \"GET /favicon.ico HTTP/1.0\" 200 3638" }
{ "create":{ } }
{ "@timestamp": "2099-05-06T16:27:42.000Z", "message": "192.0.2.255 - - [06/May/2099:16:25:42 +0000] \"GET /favicon.ico HTTP/1.0\" 200 3638" }


POST /my-data-stream/_rollover #備注1
{
  "conditions" : {
    "max_age": "7d",
    "max_docs": 2,
    "max_size": "5gb"
  }
}
           

如果目前的寫資料索引滿足條件集中的任何一個條件;則滾動目标将建立一個新的

backing

索引

my-data-stream-000002

,且新的

backing

索引将作為寫入資料的索引。

上面代碼塊的 Rollover API 傳回值如下:

{
  "acknowledged" : false,
  "shards_acknowledged" : false,
  "old_index" : ".ds-my-data-stream-000001",#資料流之前對應的寫資料索引
  "new_index" : ".ds-my-data-stream-000002",,#資料流新對應的寫資料索引
  "rolled_over" : true,#索引是否執行滾動
  "dry_run" : false,  # 是否為 dry_run 模式
  "conditions" : { # 滾動條件集,集觸發情況
    "[max_size: 5gb]" : false,
    "[max_docs: 2]" : true,
    "[max_age: 7d]" : false
  }
}           

再次檢視資料流

{
  "data_streams" : [
    {
      "name" : "my-data-stream", # 資料流名稱
      "timestamp_field" : {
        "name" : "@timestamp"
      },
      "indices" : [
        {
          # backing索引
          "index_name" : ".ds-my-data-stream-000001",
          "index_uuid" : "Vir6yRm4S42k8n22mZ5YBw"
        },
        {
          "index_name" : ".ds-my-data-stream-000002",
          "index_uuid" : "WcctdbIqSMqk3MmefRdfDQ"
        }
      ],
      "generation" : 2, #目前是那一個版本的後備索引作為寫索引
      "status" : "GREEN",
      "template" : "my-index-template", # 适配的索引模闆
      "ilm_policy" : "my-lifecycle-policy"
    }
  ]
}

           

也可以通過 Kibana 進行檢視

Rollover API— Elastic Stack 實戰手冊

目标索引設定 setting

新索引的

setting

mapping

aliases

可以取自索引名比對的任何索引模闆。如果

<rollover-target>

為索引别名,你可以在

rollover API

的請求體中指定

settings

mappings

aliases

,與建立索引的API(create index API)類似。如果請求體指定的值優先于比對的索引模闆。

如下示例重寫了 index.number_of_shards setting:

PUT /logs-000001
{
  "aliases": {
    "logs_write": {}
  }
}

POST /logs_write/_rollover
{
  "conditions" : {
    "max_age": "7d",
    "max_docs": 2,
    "max_size": "5gb"
  },
  "settings": {
    "index.number_of_shards": 2
  }
}           

指定目标索引名稱

<rollover-target>

是索引别名,并且綁定的索引名稱以

-<number>

結尾;如果不指定目标索引,發生滾動時生成的新索引名稱為 indexName-6 位數字,每滾動一次數字自增一次。

例如索引為

logs-1

(或者

logs-000001

),執行滾動後新的索引名字為

logs-000002

,6位數字低位自增高位補 0。

如果舊的索引名稱不滿足

indexName-<number>

結尾,則執行滾動必須指定新索引名字;

示例如下:

# my_alias綁定的索引索引名稱不滿足indexName-<number>格式
#必須指定索引my_new_index_name
POST /my_alias/_rollover/my_new_index_name
{
  "conditions": {
    "max_age":   "7d",
    "max_docs":  2,
    "max_size": "5gb"
  }
}           

基于 date math 滾動

<rollover-target>

是索引别名,使用 date math 根據索引滾動的目前日期來命名滾動索引;在某些場景中是非常有用的,比如定時按天删除索引、按天查詢資料等。rollover API 支援 date math,但是要求索引名稱必須以日期

-<number>

結尾,

例如:

logstash-2021.05.06-1

;以這種格式命名的主要是友善在任何時候執行滾動,索引名稱自增。

# PUT /<logs-{now/d}-1> with URI encoding:
PUT /%3Clogs_%7Bnow%2Fd%7D-1%3E #備注1 
{
  "aliases": {
    "logs_write": {}
  }
}

PUT logs_write/_doc/1
{
  "message": "a dummy log"
}

POST logs_write/_refresh

# 立即執行 _rollover 
POST /logs_write/_rollover #備注2
{
  "conditions": {
    "max_docs":   1,
    "max_age":   "1d",
    "max_size": "5gb"
  }
}           

建立一個索引取今天的日期,

logs_2021.05.06-1

執行滾動操作,如果立即執行,則新索引名為

logs_2021.05.06-000002

;如果等到24小時之後執行索引名稱為

logs_2021.05.07-000002

你可以按照 date math 文檔的說明去使用這些索引。

例如,你需要搜尋過去三天索引的資料,你可以按照如下的書寫方式:

# GET /<logs-{now/d}-*>,<logs-{now/d-1d}-*>,<logs-{now/d-2d}-*>/_search
GET /%3Clogs-%7Bnow%2Fd%7D-*%3E%2C%3Clogs-%7Bnow%2Fd-1d%7D-*%3E%2C%3Clogs-%7Bnow%2Fd-2d%7D-*%3E/_search           

Dry run

rollover API

支援

dry_run

模式,該模式主要用于條件檢測。比如想檢測索引是否滿足設定的條件完成滾動。

POST /logs_write/_rollover?dry_run
{
  "conditions" : {
    "max_age": "7d",
    "max_docs": 1000,
    "max_size": "5gb"
  }
}           

傳回值如下:

{
  "acknowledged" : false,
  "shards_acknowledged" : false,
  "old_index" : "logs-000002", #目前索引
  "new_index" : "logs-000003",# 将要新生成的索引
  "rolled_over" : false, #是否完成滾動
  "dry_run" : true,  # 是否為檢測模式
  "conditions" : {
    "[max_size: 5gb]" : false,
    "[max_docs: 1000]" : false,
    "[max_age: 7d]" : false
  }
}           

基于 write index 滾動

基于

write index

滾動主要是為了解決,使用别名查詢能夠擷取到之前建立的索引資料,以及同一别名綁定多個索引滾動切換歧義問題。同一個别名具有查詢和寫入兩種特性。

示例如下

#建立一個索引,綁定别名 logs,并标注 is_write_index 為 true,即通過别名寫入資料,實際是寫入到 my_logs_index-000001 表中
PUT my_logs_index-000001
{
  "aliases": {
    "logs": { "is_write_index": true } 
  }
}
#寫入一個文檔
PUT logs/_doc/1
{
  "message": "a dummy log"
}
#重新整理,生成一個 segements,使文檔變得可搜尋
POST logs/_refresh
#執行滾動操作
POST /logs/_rollover #備注1
{ 
  "aliases": {"search_all": {}}, #備注2
  "conditions": {
    "max_docs":   "1"
  }
}
#再次基于别名寫入
PUT logs/_doc/2 
{
  "message": "a newer log"
}           

執行滾動操作

write index

切換成為新建立的索引,之後寫入的資料将寫入到新索引中,滾動時新産生的索引添加别名

search_all

上述代碼塊執行

_rollover

的傳回值如下

{
  "_index" : "my_logs_index-000002",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}           

在完成滾動之後,

GET _alias/logs

,檢視别名元資訊,可以發現新索引已經作為

write index

{
  "my_logs_index-000002": {
    "aliases": {
      "logs": { "is_write_index": true }
    }
  },
  "my_logs_index-000001": {
    "aliases": {
      "logs": { "is_write_index" : false }
    }
  }
}
           

基于 ILM 實作自動 Rollover

首先在 Kibana ,定義生命周期政策(也可通過 API 方式);

下圖規定了 Hot 階段重新生成索引的規則,這部分功能其實就是對于

rollover API

的封裝;下圖中我們定義了一個名稱為

rollover-test-all

的生命周期管理政策,其中滾動條件為

max_size

,為 20gb,

max_age

為 1 天,

max_docs

為 2;

Rollover API— Elastic Stack 實戰手冊

我們可以通過 API,檢視

GET _ilm/policy/rollover-test-all

。傳回值如下:

{
  "rollover-test-all" : {
    "version" : 1,
    "modified_date" : "2021-05-11T15:23:27.155Z",
    "policy" : {
      "phases" : {
        "hot" : {
          "min_age" : "0ms",
          "actions" : {
            "rollover" : {
              "max_size" : "20gb",
              "max_age" : "1d",
              "max_docs" : 2
            },
            "set_priority" : {
              "priority" : 100
            }
          }
        }
      }
    }
  }
}           

建立一個模闆,模版中引用剛才定義的生命周期政策,并指定滾動的别名。

關于索引模闆更多資訊請參看 Simulate multi-component templates
# 這個是 legacy 的 index template,适用于 7.8 版本以前,
# 但在7.11版本,仍然可以用
PUT _template/iml-rollover_template
{
  "index_patterns": [
    "iml-rollover*"
  ],
  "aliases": {
    "iml-rollover_alias": {}
  },
  "settings": {
    "index": {
      "lifecycle": {
        "name": "rollover-test-all",
        "rollover_alias" : "iml-rollover_write_alias"
      },
      "refresh_interval": "2s",
      "number_of_shards": "1",
      "number_of_replicas": "0"
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      }
    }
  }
}

# 7.8 版本之後,可以使用 _index_template 定義模闆;
PUT _index_template/iml-rollover_template
{
  "index_patterns": ["iml-rollover*"],
  "template": {
    "settings": {
      "lifecycle": {
        "name": "rollover-test-all",
        "rollover_alias" : "iml-rollover_write_alias"
      },
      "refresh_interval": "2s",
      "number_of_shards": "1",
      "number_of_replicas": "0"
    },
    "mappings": {
      "_source": {
        "enabled": true
      },
      "properties": {
      "name": {
        "type": "keyword"
      }
    }
    },
    "aliases": {
      "iml-rollover_alias": { }
    }
  },
  "priority": 500,
  "_meta": {
    "description": "my custom rollover test"
  }
}
           
PUT iml-rollover-000001
{
  "aliases": {
    "iml-rollover_write_alias": {  "is_write_index": true  }
  }
}           

插入資料

PUT iml-rollover_write_alias/_bulk?refresh=true
{"index":{}}
{"name":"kimchy"}
{"index":{}}
{"name":"tom"}           

檢視索引情況

GET _cat/indices/iml-rollover-*?v&h=health,index,docs.count

結果如下

health index               docs.count
green  iml-rollover-000001          2
green  iml-rollover-000002          0           

iml-rollover-000001 的文檔個數為 2,并且 iml-rollover-000002 索引已經被建立。檢視别名的關聯關系

GET _cat/aliases/iml-rollover_*?format=json

。索引 iml-rollover-000002 的别名 iml-rollover_write_alias 被标記為具有寫權限。

[
  {
    "alias" : "iml-rollover_alias",
    "index" : "iml-rollover-000001",
    "filter" : "-",
    "routing.index" : "-",
    "routing.search" : "-",
    "is_write_index" : "-"
  },
  {
    "alias" : "iml-rollover_write_alias",
    "index" : "iml-rollover-000001",
    "filter" : "-",
    "routing.index" : "-",
    "routing.search" : "-",
    "is_write_index" : "false"
  },
  {
    "alias" : "iml-rollover_alias",
    "index" : "iml-rollover-000002",
    "filter" : "-",
    "routing.index" : "-",
    "routing.search" : "-",
    "is_write_index" : "-"
  },
  {
    "alias" : "iml-rollover_write_alias",
    "index" : "iml-rollover-000002",
    "filter" : "-",
    "routing.index" : "-",
    "routing.search" : "-",
    "is_write_index" : "true"
  }
]           

和預期是一緻的,正确的完成滾動。這時通過

iml-rollover_write_alias

寫入資料,資料被寫入到

iml-rollover-000002

索引中。再次執行插入資料語句,然後檢視索引文檔。

health index               docs.count
green  iml-rollover-000001          2
green  iml-rollover-000002          2