天天看點

Elasticsearch 7.X data stream 深入詳解

記得第一次聽到 data stream 的時候,還是去年下半年在公交大巴車上早 8 點聽魏彬老師的直播,後來就一直沒用。

等使用的時候,去翻看文檔和資料前,從認知的角度,不免會有如下的疑問:

沒有 data stream 的時候,如何管理時序型資料?

什麼是 data stream?

data stream 的特點有哪些?

為什麼要有 data stream?

data stream 能做什麼?

data stream 應用場景?

data stream 和 索引 index 的關系?

data stream 和 索引生命周期管理 ILM 的關系?

data stream 實操有哪些注意事項?

帶着這些問題,我們開始下面的解讀。

PS:說明一下:後面所有博文的參考内容(含官方文檔)都會寫明詳盡的參考位址,以便大家參考學習。

0、認知前提

0.1 時序性資料

指那種每天新增資料量非常大、且包含時間戳特性、有時效性特點的資料。

時效性展現在:使用者往往更傾向關注最新、最熱、最實時的資料。

比如:日志資料、大資料輿情資料等。

0.2 rollover

滾動索引,可以基于:時間間隔、文檔數、分片大小進行滾動。

0.3 ILM

ILM = 索引生命周期管理的英文首字母組合。

1、沒有 data stream 的時候,如何管理時序型資料?

實戰一把,說的清楚。

1.1 基于 rollover 滾動索引機制管理時序資料

時序性索引資料,5.X 版本推出的rollover 滾動索引機制操作步驟如下:

步驟1:建立日期序列索引。

PUT /%3Cmylogs-%7Bnow%2Fd%7D-1%3E

{

 "aliases": {

   "mylogs_write": {}

 }

}

GET mylogs-2021.07.24-1

步驟2:插入一條資料

PUT mylogs_write/_doc/1

 "message": "a dummy log"

步驟3:導入資料

POST mylogs_write/_bulk

{"index":{"_id":4}}

{"title":"test 04"}

{"index":{"_id":2}}

{"title":"test 02"}

{"index":{"_id":3}}

{"title":"test 03"}

步驟4:指定RollOver規則(必須手動指定)

POST  mylogs_write/_rollover

 "conditions": {

   "max_docs":   3

步驟5:再次導入批量資料

POST mylogs_write/_doc/14

{"title":"test 14"}

{"index":{"_id":5}}

{"title":"test 05"}

{"index":{"_id":6}}

{"title":"test 06"}

{"index":{"_id":7}}

{"title":"test 07"}

{"index":{"_id":8}}

{"title":"test 08"}

{"index":{"_id":9}}

{"title":"test 09"}

{"index":{"_id":10}}

{"title":"test 10"}

早期生産環境使用 rollover,有個比較麻煩的地方就在于——需要自己結合滾動的三條件,在給定的時間點(比如淩晨0:00)定時腳本執行一下 rollover,滾動才能生效。

看似腳本處理很簡單,實際會有這樣那樣的問題,用過你就知道有多苦。

rollover 優點:實作了最原始的索引滾動。

rollover 缺點:需要手動或者腳本定時 rollover 非常麻煩。

這時候,讀者不禁要問,ILM 索引生命周期管理操作時序資料呢?

1.2 ILM 索引生命周期管理時序資料

篇幅原因,不再舉例。可以參考:幹貨 | Elasticsearch 索引生命周期管理 ILM 實戰指南。

ILM 是模闆、别名、生命周期 policy 的綜合體。

ILM 優點:一次配置,索引生命周期全自動化。

ILM 适用場景:更适合和冷熱叢集架構結合的業務場景。

ILM 缺點:ILM是普适的概念,強調大而全,不是專門針對時序資料特點的方案,且需要為 ilm 配置 index.lifecycle.rollover_alias 設定(對時序資料場景,這非常麻煩)。

上述 rollover、ILM 機制實作:都涉及到多索引和别名的關系。

官方強調:别名在 Elasticsearch 中的實作方式存在一些不足(官方沒有細說哪些不足。我實戰環境發現:一個别名對應多個索引,一個索引對應多個别名,索引滾動關聯别名也可能滾動,開發者可能很容易出錯和混淆),使用起來很混亂。

相比于别名具有廣泛的用途,而資料流将是針對時序資料的解決方案。

2、什麼是 data stream?

data:資料。

stream:流。

data stream:資料流。

我X,這英語翻譯,國小生也會。沒勁!能不能通俗點說?

我把 data stream 比如:存儲時序資料的多個索引的抽象集合,簡稱為:資料流(data stream)。

資料流可以跨多個後備索引存儲僅追加(append-only,下文有詳細解釋)的時間序列資料,同時對外提供一個同一通路入口。

上面 data stream 的定義和别名的定義貌似一緻,國外部落客把它戲稱為“超能力别名”,我認為非常生動和貼切。

和别名不同的是:别名關聯多個索引,寫入的時候需要指定 “is_write_index",而 data stream 相對黑盒,這些細節使用者無需關注。

是以,它是索引、模闆、rollover、ilm 基于時序性資料的綜合産物。

3、data stream 的特點有哪些?

3.1 關聯後備支撐索引(backing indices)

data stream 作為“帶頭大哥”在外抛頭露面,實際後面一堆“小弟”在全力支撐。

Elasticsearch 7.X data stream 深入詳解

“帶頭大哥”指的是:資料流。它的特點:抛頭露面、光鮮亮麗。

“小弟”:指 backing indices,後備索引。它的特點:相對隐身、默默無聞。其實出力的都是它,除非大哥出事(一些特定限制搞不定),小弟們才會站出來。

3.2 @timestamp 字段不可缺

每個寫入到 dataSteam 的文檔必須包含 @timestamp 字段。

@timestamp 字段必須是:date 類型(若不指定,預設:date 類型)或者 date_nanos 類型。

3.3 data stream 後備索引規範

建立後備索引時,索引使用以下約定命名:

.ds-<data-stream>-<yyyy.MM.dd>-<generation>

舉例索引真實名稱:data-stream-2021.07.25-000001。

.ds:字首開頭不可少。

data-stream: 自定義的資料流的名稱。

yyyy.MM.dd:日期格式

generation:rollover 累積值:—— 預設從:000001 開始。

3.4 Append-only 僅追加

僅追加:指隻支援 op_type=create 的索引請求,我了解的是僅支援向後追加(差別于對曆史資料的删除、更新操作)。

資料流隻支援:update_by_query 和 delete_by_query 實作批量操作,單條文檔的更新和删除操作隻能通過指定後備索引的方式實作。

對于頻繁更新或者删除文檔的業務場景,用 data stream 不合适,而相反的,使用:模闆+别名+ILM更為合适。

4、為什麼要有 data stream?

原有實作由于别名的缺陷實作不了時序資料的管理或實作起來會繁瑣、麻煩,data stream 是更為純粹的存儲僅追加時序資料的方式。

5、data stream 能做什麼?

data stream 支援直接的寫入、查詢請求。

data stream 會自動将用戶端請求路由至關聯索引,以用來存儲流式資料。

可以使用索引生命周期管理 ILM 自動管理這些關聯索引。

6、data stream 的适用場景

日志(logs)、事件(events)、名額(metrics)和其他持續生成的資料。

兩大核心特點:

時序性資料。

資料極少更新(或者沒有更新)。

7、data stream 和索引有什麼異同?

7.1 相同點

絕大多數指令一緻。

7.2 不同點

資料流相對實體索引,有點“抽象層“的概念,其核心資料還是存儲在 .ds 字首的後備索引中。

以下操作,隻适用于資料流。

資料流對應映射必須包含日期類型的 @timestamp 字段。

資料流删除和更新隻支援 “_update_by_query” 和 “_delete_by_query”操作。

不能基于.ds 字首的後備索引建立文檔,但可以基于:以.ds字首的後備索引更新和删除文檔。

我不聽,我非要指定後備索引寫入一條資料,咋辦?試試吧:

POST .ds-my-data-stream-2021.07.25-000001/_doc/2

 "@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"

會有如下的報錯提示:不支援指定後備索引寫入,隻能基于資料流寫入。

 "reason" : "index request with op_type=index and no if_primary_term and if_seq_no set targeting backing indices is disallowed, target corresponding data stream [my-data-stream] instead"

也就是說:隻能基于資料流寫入資料。

不能對後備索引執行:clone, close, delete, freeze, shrink 和 split 操作。

8、data stream 和 模闆的關系?

相同的索引模闆可以用來支撐多個 data streams。可以類比為:1:N 關系。

不能通過 删除 data Stream 的方式删除索引模闆。

9、data stream  和 ilm 的關系?

ILM 在 data stream 中起到索引生命周期管理的作用。

data stream 操作時序資料優勢展現在:不再需要為 ilm 配置 index.lifecycle.rollover_alias。

10、data stream 實操指南

涉及 data stream 的建立(新增)、删除、修改、查詢。

10.1 data stream 增

由于 data stream 涉及模闆、索引、ILM、别名等,分步驟拆解更好了解。

步驟 1:建立索引生命周期 policy。

直接拿官方文檔的示例說明。

如下的 policy 包含了:熱、暖、冷、冷凍、删除等階段。

PUT _ilm/policy/my-lifecycle-policy

 "policy": {

   "phases": {

     "hot": {

       "actions": {

         "rollover": {

           "max_primary_shard_size": "50gb"

         }

       }

     },

     "warm": {

       "min_age": "30d",

         "shrink": {

           "number_of_shards": 1

         },

         "forcemerge": {

           "max_num_segments": 1

     "cold": {

       "min_age": "60d",

         "searchable_snapshot": {

           "snapshot_repository": "found-snapshots"

     "frozen": {

       "min_age": "90d",

     "delete": {

       "min_age": "735d",

         "delete": {}

     }

   }

步驟 2:建立模闆

模闆組成包括:index_patterns、指定資料流 data stream、settings、mappings。

PUT _component_template/my-mappings

 "template": {

   "mappings": {

     "properties": {

       "@timestamp": {

         "type": "date",

         "format": "date_optional_time||epoch_millis"

       },

       "message": {

         "type": "wildcard"

# Creates a component template for index settings

PUT _component_template/my-settings

   "settings": {

     "index.lifecycle.name": "my-lifecycle-policy"

PUT _index_template/my-index-template

 "index_patterns": ["my-data-stream*"],

 "data_stream": { },

 "composed_of": [ "my-mappings", "my-settings" ],

 "priority": 500

步驟 3:建立 data stream 。

方式一:直接建立資料流 my-data-stream。

PUT _data_stream/my-data-stream

方式二:直接批量或者逐個導入資料(會間接生成 data stream 的建立)。

Elasticsearch 7.X data stream 深入詳解

PUT my-data-stream/_bulk

{ "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" }

{ "@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" }

POST my-data-stream/_doc

兩個注意的地方:

第一:批量 bulk 操作,必須使用:create 指令,而非 index(使用 index 不會報錯, 會把流當做索引處理了)。

第二:文檔必須包含:@timestamp  時間戳字段。

如果不包含 @timestamp 會報錯如下:

 "reason" : "data stream timestamp field [@timestamp] is missing"

10.2 data stream 删

删除資料流

删除 data stream 和 删除索引、删除模闆文法基本一緻。

DELETE _data_stream/my-data-stream

執行删除操作之後,該 data stream 以及 關聯索引都會被一并删除。

單條删除文檔

DELETE data-stream-2021.07.25-000001/_doc/1

批量删除文檔

批量删除資料的方式如下:

POST /my-data-stream/_delete_by_query

 "query": {

   "match": {

     "user.id": "vlb44hny"

10.3 data stream 改

單條資料修改/更新

# 插入一條資料

POST my-data-stream/_bulk

{"create":{"_id":1}}

{"@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"}

# 擷取資料流關聯索引

GET /_data_stream/my-data-stream

# 執行更新

PUT .ds-my-data-stream-2021.07.25-000001/_doc/1?if_seq_no=1&if_primary_term=1

 "@timestamp": "2099-03-08T11:06:07.000Z",

 "user": {

   "id": "8a4f500d"

 },

 "message": "Login successful"

# 檢視驗證是否已經更新(已經驗證,可以更新)

GET .ds-my-data-stream-2021.07.25-000001/_doc/1

這裡要強調:原來更新單條索引資料的 _update/id 的方法不适用于資料流。

批量更新

支援通過:update_by_query 批量更新資料。

POST /my-data-stream/_update_by_query

     "user.id": "l7gk7f82"

 "script": {

   "source": "ctx._source.user.id = params.new_id",

   "params": {

     "new_id": "XgdX0NoX"

10.4 data stream 查

GET _data_stream/my-data-stream

Elasticsearch 7.X data stream 深入詳解

傳回結果如下:

 "data_streams" : [

   {

     "name" : "my-data-stream",

     "timestamp_field" : {

       "name" : "@timestamp"

     "indices" : [

       {

         "index_name" : ".ds-my-data-stream-2021.07.25-000001",

         "index_uuid" : "Akg3-bWgStiKG_39Tk5PRw"

     ],

     "generation" : 1,

     "status" : "GREEN",

     "template" : "my-index-template",

     "ilm_policy" : "my-lifecycle-policy",

     "hidden" : false

 ]

10.5 其他操作

reindex 操作

POST /_reindex

 "source": {

   "index": "archive"

 "dest": {

   "index": "my-data-stream",

   "op_type": "create"

滾動操作

POST my-data-stream/_rollover

檢視 data stream 基礎資訊

11、小結

在規劃産品的時候,往往會細數一下産品的新功能,這些新功能可能是:內建競品、原創更新、其他産品線功能更新等。

data stream 這個 7.9 版本才推出的新功能點,其實是基于原有實作不能滿足時序資料特點,更為确切說原有實作機制相對複雜而推出的新功能。

提煉一下本文内容,劃重點如下:data stream 是時序索引的上層抽象。

data stream 是模闆、索引、settings、mappings、ilm policy等綜合體的概念。

data stream 相當于抛頭露面的帶頭大哥,離不開看似隐身、默默無聞、實際埋頭苦幹的後備索引的支撐。

data stream 不适合頻繁删除、更新的業務場景,更适合僅追加時序資料場景。

隻能基于 data stream 寫入資料,不能基于後備索引寫入資料。

data stream 不支援單條删除或單條更新資料,隻支援:update_by_query 以及 delete_by_query。

參考

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/data-streams.html https://opster.com/elasticsearch-glossary/elasticsearch-data-streams/ https://aravind.dev/elastic-data-stream/ https://github.com/elastic/elasticsearch/issues/53100 https://www.elastic.co/guide/en/elasticsearch/reference/7.13/release-notes-7.9.0.html

繼續閱讀