写点什么

Elasticsearch 可搜索快照技术原理及最佳实践

  • 2021 年 12 月 29 日
  • 本文字数:6323 字

    阅读完需:约 21 分钟

Elasticsearch 可搜索快照技术原理及最佳实践

作者:吴容——腾讯云 Elasticsearch 高级开发工程师

Elasticsearch 于 7.10 版本推出可搜索快照功能,但是 7.10 版本的可搜索快照技术还不够成熟,随着 7.14 版本的发布,可搜索快照技术才真正能够大规模用于生产实践中。本文将基于 ES 7.14.2 版本,继续从原理和实践两个角度向大家介绍可搜索快照技术。

可搜索快照特性向我们展现一种能够直接搜索快照中数据的魔力,通常我们会将快照备份到非常廉价的存储介质中,如腾讯云对象存储 COS 中。这样我们就可以将集群的使用成本降到最低。

一、可搜索快照技术原理

1.1 DataTier 模型

要了解可搜索快照的工作机制,首先我们需要了解从 7.10 版本开始 ES 对节点的分层规划,即 DataTier(https://www.elastic.co/guide/en/elasticsearch/reference/7.15/data-tiers.html#frozen-tier)概念。

ES 对不同的节点类型做了如下分层,分别是 Content tier、Hot tier、Warm tier、Cold tier 和 Frozen tier。

  • Content tier:主要处理产品目录等内容型索引和查询负载;

  • Hot tier:主要处理数据的读写,尤其是时序类数据的写入和查询,由于对读写性能要求最高,并且查询的频率也最高,因此我们建议对于 Hot tier 的节点挂载 SSD 硬盘;

  • Warm tier:主要处理时序类场景数据,数据不再被更新,查询频率相对 Hot tier 节点较低;

  • Cold tier:主要处理数据的读请求,且查询的数据较老,通常查询频率更低,因此建议 Warm/Cold tier 的节点挂载 HDD;

  • Frozen tier:查询的频率更低,可能半年才查询那么几次,但是这种数据体量其实是最大的;于 Frozen tier 中的数据,则是通过可搜索快照的技术挂载在集群中的。原始的数据其实是在快照中,集群中只会保存索引的元数据相关信息,以及每次查询时的缓存数据。

1.2 节点属性优化

另外 7.10 版本之后的集群不再通过 node.master,node.data 来区分是何种角色的节点,而是通过 node.roles 数组来定义一个节点的角色。如我们的测试集群中,Hot tier 节点的 node.roles 如下:

node.roles: ["data_hot", "data_content", "ingest", "ml", "remote_cluster_client", "transform"]
复制代码

专用主节点的 node.roles 则是:

node.roles: ["master"]
复制代码

如果集群中有 Frozen tier 的节点,我们通过是将该节点设置为专用 Frozen 节点,不和任何角色混用,如设置 node.roles 如下:

node.roles: ["data_frozen"]
复制代码

除了对节点角色的优化,还对索引的 allocation 做了优化,原先我们是通过 include.{attribute}、require.{attribute}、exclude.{attribute}来设置索引的 allocation settings;而升级到 DataTier 模式后,则是通过 index.routing.allocation.include._tier_preferencehttps://www.elastic.co/guide/en/elasticsearch/reference/7.15/data-tier-shard-filtering.html#tier-preference-allocation-filter属性决定索引分片应该分配在哪一 Tier 节点上。

index.routing.allocation.include._tier_preference 的属性值是一个字符串,多个 tier_preference 之间通过逗号 ',' 隔开,分片分配的优先级是从前往后依次降低。例如集群中的系统索引.kibana_7.14.2_001 在创建时,其 index.routing.allocation.include._tier_preference 属性值为:"data_hot,data_warm,data_cold",如下图 1 所示:



图 1. 索引创建时的_tier_preference 属性


该属性的具体分配逻辑为:当集群中有 data_hot 节点时,则直接将分片分配在 data_hot 节点上,当没有 data_hot 节点时,则检查是否有 data_warm 节点,如果有,则在 data_warm 节点上分配,没有则在 data_cold 节点上分配。因此如果我们希望对集群中的数据进行降冷时,只需要将待降冷的索引 settings 设置为如下即可:

PUT {index_name}/_settings{  "index": {    "routing": {      "allocation": {        "include": {          "_tier_preference": "data_warm,data_cold,data_hot"        }      }    }  }}
复制代码


1.3 工作原理

上面我们介绍了下 7.10 版本中引入的 DataTier 和_tier_preference 概念,之所以先了解 DataTier,是因为可搜索快照有两种挂载模式,分别对应的是两类不同的节点角色,即我们通过使用 Cold 或者 Frozen 数据节点来挂载可搜索快照数据,从而大大降低我们的集群成本。

若要对快照中数据进行查询,首先我们需要将快照中的数据 Mount(https://www.elastic.co/guide/en/elasticsearch/reference/7.15/searchable-snapshots-api-mount-snapshot.html)到集群中,而不是直接通过 API 去 Search 快照中的数据。

  • 全量挂载(Fully mounted index)

全量挂载的意思就是将快照中索引的数据在 ES 集群节点上全量保留一份,当搜索全量挂载的可搜索快照索引时,搜索原理和性能和普通索引相差不大。相比普通索引的优势在于,当其中一个分片出现损坏时,可搜索快照索引会自动从快照中拉取数据在其他节点上进行恢复,尤其是在集群中没有副本的情况下,普通模式是集群直接 red,如果需要恢复,则必须手动从快照中进行恢复,在恢复前还需要先将该 red 的索引删除,而通过 mount 挂载下来的索引,则自动从快照中恢复损坏的分片。

  • 部分挂载(Partially mounted index)

部分挂载的意思就是并不将快照中的索引数据 mount 到集群节点上,而是只将索引的元数据信息保存以索引和分片的形式保留在节点上。部分挂载的分片只会分配在 Frozen 层。因此集群中 Frozen 层节点不存储快照数据,只存储索引分片的元数据信息,原始数据存储在 COS 的快照仓库中。如下 API 样例所示,其中 storage 就是索引的挂载类型:full_copy 是全量挂载,而 shared_cache 则为部分挂载。

POST /_snapshot/default_searchable_snapshot_repository/my_cos_snapshot/_mount?wait_for_completion=true&storage=shared_cache{  "index": "wurong-test-2021.11.26-000001",   "renamed_index": "wurong-test-2021.11.26-000001_from_cos",   "index_settings": {     "index.number_of_replicas": 0  },  "ignore_index_settings": [ "index.refresh_interval" ] }
复制代码

当查询部分挂载的可搜索快照索引时,会从快照中进行拉取并加载在 Frozen 层节点本地缓存中,下次查询类似数据时则可以直接从本地进行返回,另外 ES 也有缓存淘汰策略,会定期清理不再经常查询的缓存数据以释放空间。通常需要配置一个或多个专用 Frozen 节点,这些专用 Frozen 节点之间共享缓存。如果集群中没有配置专用 Frozen 节点,则必须在节点的配置文件中配置如下参数 xpack.searchable.snapshot.shared_cache.size 来设置每个节点中需要为共享缓存保留的存储空间。因为部分挂载的可搜索快照索引只会在分配在具有共享缓存的节点上。

另外由于 Frozen 节点上存储的是索引的元数据信息,以及查询的缓存数据。因此在配置 Frozen 节点时,需要给共享缓存预留一定的硬盘空间,默认需要保留至少 90%的磁盘总容量,如图 2 所示,通过 xpack.searchable.snapshot.shared_cache.size 参数进行调整。



图 2. Frozen 节点磁盘使用率

由于该参数是一个 static 类型,因此当我们给 Frozen 节点的硬盘进行扩容时,如采用腾讯云 CBS 的弹性拉伸时扩容时,则需要重启 Frozen 节点才能使得 xpack.searchable.snapshot.shared_cache.size 参数生效。

查询 Frozen 节点上的数据需要先将索引数据下拉到本地节点上才开始执行 Search 查询。因此查询时间上必然是比全量挂载或者查询普通的索引慢很多的,为了解决这个问题,ES 提供了一种 Async Search(https://www.elastic.co/guide/en/elasticsearch/reference/7.15/async-search.html)异步搜索的 API。当执行该 API 时候,并不会立即获取到查询结果,而是返回一个 requestId,随后异步准备数据,当数据准备好后,只需要通过该 requestId 即可获取到想要的数据了(以下样例来源官网)。

POST /sale*/_async_search?size=0{  "sort": [    { "date": { "order": "asc" } }  ],  "aggs": {    "sale_date": {      "date_histogram": {        "field": "date",        "calendar_interval": "1d"      }    }  }}
复制代码

由此我们可以看出 Frozen 层的部分挂载模式才是可搜索快照技术的真正亮点,因为它只需要 Frozen 节点很少的硬盘空间,即可 Search 过去无限规模的数据。达到了真正降低成本的目的。

二、可搜索快照操作实践

下面我们基于腾讯云 COS 来逐步演示如何一步步搭建可搜索快照集群,我们要实现的效果是通过压测程序持续向集群中写入数据,索引在 10 分钟或者达到 10mb 后开始滚动,滚动完成后 1 小时开始迁移到冷节点上,并且执行 COS 备份,备份完成后全量挂载到集群中,删除集群中原来的索引数据,2 小时后将索引部分挂载到集群中,此时索引分片分配在冻结层。其数据流转架构如下图 3 所示:



图 3. 可搜索快照演练数据流转示意图


2.1 集群环境准备

我们搭建的集群是 7.14.2 版本,由于可搜索快照技术只能在企业版本使用,因此我们在创建出 7.14 集群后需要手动调下如下 API 来免费试用企业版:

POST /_license/start_trial?acknowledge=true
复制代码

调用 API 后如图 4 所示,说明当前集群已经是企业版集群了。



图 4. 激活企业版 License


2.2 创建快照仓库

本文测试集群使用的是腾讯云 COS,因此我们需要在集群中创建一个 COS 仓库,用于可搜索快照的存放,,仓库名称为 default_searchable_snapshot_repository。

PUT _snapshot/default_searchable_snapshot_repository{    "type": "cos",    "settings": {        "app_id": "1254139681",        "access_key_id": "xxxx",        "access_key_secret": "xxxx",        "bucket": "wurong-es-snapshpt",        "region": “ap-guangzhou",        "compress": true,        "chunk_size": "500mb",        "base_path": "/searchable-snapshot"    }}
复制代码


2.3 配置索引生命周期管理

  • 配置 ILM 的 Policy

首先我们在 Kibana 上配置索引生命周期管理的 Policy,路径为:Management-Stack Management-Data-Index Lifecycle Polices。主要是设置 ILM 的策略名称,每个 Phase 的触发 Condition。



图 5. 配置 ILM 的 Policy-Hot phase

上面我们设置好了 Hot phase,主要是设置 Rollover 的触发条件,我们希望索引在创建后 20 分钟,或者主分片容量达到 10mb 后触发滚动,写入下一个索引。



图 6. 配置 ILM 的 Policy-Cold/Frozen phase

图 6 我们配置了 Cold/Frozen phase 的信息。我们想要达到的效果是索引在触发 Rollover 后的 1 小时开始降冷,将数据迁移到 Cold tier 上来,并且将数据备份到 COS 仓库,然后再全量 Mount 到集群中,在然后 2 小时后将 cos 中的索引部分 mount 到集群中。

上面我们是通过 Kibana 进行配置的,我们也可以直接通过 API 进行配置,效果是一样的:

PUT _ilm/policy/searchable_snapshot_test_policy {    "policy": {        "phases": {            "hot": {                "min_age": "0ms",                 "actions": {                    "rollover": {                        "max_size": "100mb",                         "max_primary_shard_size": "10mb",                         "max_age": "20m",                         "max_docs": 1000000                    },                     "set_priority": {                        "priority": 100                    }                }            },             "cold": {                "min_age": "1h",                 "actions": {                    "searchable_snapshot": {                        "snapshot_repository": "default_searchable_snapshot_repository",                         "force_merge_index": true                    },                     "set_priority": {                        "priority": 0                    },                     "allocate": {                        "number_of_replicas": 0                    }                }            },             "frozen": {                "min_age": "2h",                 "actions": {                    "searchable_snapshot": {                        "snapshot_repository": "default_searchable_snapshot_repository",                         "force_merge_index": true                    }                }            }        }    }}
复制代码
  • 配置索引模版

在索引模版中指定创建的 ILM policy 和 Rollover 别名,模版名称为 searchable_snapshot_test_template,policy 名称为 searchable_snapshot_test_policy,别名为 wurong-test,_tier_preference 为"data_hot,data_warm,data_cold"。

PUT _template/searchable_snapshot_test_template{  "order": 100,  "index_patterns": [    "wurong-test*"  ],  "settings": {    "index": {      "lifecycle": {        "name": "searchable_snapshot_test_policy",        "rollover_alias": "wurong-test"      },      "routing": {        "allocation": {          "include": {            "_tier_preference": "data_hot,data_warm,data_cold"          }        }      },      "refresh_interval": "30s",      "number_of_shards": "5",      "translog": {        "sync_interval": "5s",        "durability": "async"      },      "max_result_window": "65536",      "unassigned": {        "node_left": {          "delayed_timeout": "5m"        }      },      "number_of_replicas": "1"    }  }}
复制代码
  • 创建初始索引

我们期望在索引名称上加上日期,因此使用如下的方式进行创建。

PUT %3Cwurong-test-%7Bnow%2Fd%7D-000001%3E{"aliases": {    "wurong-test":{       "is_write_index": true        }      }}
复制代码

创建完成后可以看出索引名称上包含了当前的日期,且后缀从 000001 开始。



图 7. 创建初始索引

然后通过压测程序开始向集群中写入数据,并且通过别名进行写入。

  • 效果展示

当我们持续往集群中写入半天的数据后,可以看到部分名称是 restored-*开头的索引,这些索引就是从 COS 快照中 Mount 到本地的,如图 8 所示。



图 8. 集群中的索引信息

我们以 restored-wurong-test-2021.11.26-000001 为例子,查看该索引的 settings 信息,如下图 9 所示:



图 9. 可搜索快照索引的 settings 信息

从 restored-wurong-test-2021.11.26-000001 索引的 settings 信息中可以看出分片副本被设置为了 0,_tier_preference 也从原先的"_tier_preference": "data_hot,data_warm,data_cold”,调整成了"_tier_preference": "data_cold,data_warm,data_hot”,由此也可以看出这个索引是通过全量挂载模式 mount 到集群中的。并且在 store 对象中详细列出了 mount 快照的信息,如仓库名称,快照名称,快照 Id 和索引 Id 等。

当触发了 Frozen phase 的条件后,索引分片会被分配到 Frozen tier 节点上,且该索引是按照我们在 ILM policy 中定义的那样,通过部分挂载,即 Partially mount 模式挂载在 Frozen tier 节点上的。从 Kibana 上我们可以看到,该类索引名称是以 partial-*开头,其 Docs 数量是 7413000,但是 Storage size 大小为 0,这说明该索引在集群上是不占用存储空间的,只有索引的元数据信息。如图 10 所示:



图 10. 部分挂载的索引

查看该索引的 settings 信息,可以看到_tier_preference 被设置为了:data_frozen。



图 11. 部分挂载的索引 settings 信息

另外 ILM 自动备份的快照信息也可以直接在 Kibana 上查看,路径为:Management-Stack Management-Data-Snapshot and Restore,如图 12 所示。



图 12. Kibana 上的快照列表信息

本文介绍了可搜索快照的技术原理, 以及基于腾讯云 COS 对象存储完整演示了可搜索快照的配置过程和可搜索快照的转换流程。希望对大家有所帮助,也让我们共同期待腾讯云 ES 的可搜索快照方案的发布。


 


点击并拖拽以移动

​关注“腾讯云大数据”公众号,技术交流、最新活动、服务专享一站 Get~ 


用户头像

还未添加个人签名 2020.06.19 加入

欢迎关注,邀您一起探索数据的无限潜能!

评论

发布
暂无评论
Elasticsearch 可搜索快照技术原理及最佳实践