本文描述问题及解决方法同样适用于 腾讯云 Elasticsearch Service(ES)。
另外使用到:对象存储(Cloud Object Storage,COS)
Elasticsearch 版本:7.14.2
ES作为大数据技术栈的一员,也是当下比较流行的搜索引擎,不过随着数据量日益增长,存储成本也变得越来越高昂。比如像有些客户比较重要的日志场景,或者电商数据等,这些数据可能都需要长期保留。那么这时候存储降本的方案就显得尤为重要,今天就和大家分享一下ES的存算分离方案。
ES的存算分离技术实现,是基于快照备份的功能,在快照的基础之上增加了可搜索的能力。在介绍可搜索快照之前,我们简单复习一下ES快照的基本知识。
首次快照备份为全量备份,这里我们将快照名称记为 “快照A”。
与快照 A 关联的文件列表为:1、2、3、4。
然后我们对ES中的数据做了一些修改,导致Lucene文件发生了一些变化。由于Lucene索引段文件的特性,只会新增和删除而不会修改,因此此时的Lucene中文件可能如下图所示。然后进行第二次快照,我们将快照名称记为 “快照 B”。
与快照 B 关联的文件列表为:2、3、4、5。
最后我们删除了快照 A。
与快照 A 关联的文件是:1、2、3、4;
与快照 B 关联的文件是:2、3、4、5;
所以删除快照 A时,只有文件 1 可以被删除。
1、删除历史快照会对增量快照造成影响吗?
答:不会,以上快照逻辑为例,删除历史快照只会清理不被任何快照关联的文件,每个完整的快照都能还原当时的全量数据。
2、恢复完整数据的时候要如何恢复?需要从第一个快照开始一个一个恢复吗?
答:不需要,只需恢复指定时间点的快照即可,因为每个快照都保留了那个时间点的全量数据。
全量挂载就是将快照中索引的数据在 ES 集群节点上全量保留一份,当搜索全量挂载的可搜索快照索引时,搜索原理和性能和普通索引相差不大。相比普通索引的优势在于,当其中一个分片出现损坏时,可搜索快照索引会自动从快照中拉取数据在其他节点上进行恢复,尤其是在集群中没有副本的情况下,普通模式是集群直接 red,如果需要恢复,则必须手动从快照中进行恢复,在恢复前还需要先将该red的索引删除,而通过 mount 挂载下来的索引,则自动从快照中恢复损坏的分片。
部分挂载并不将快照中的索引数据mount到集群节点上,而是只将索引的元数据信息保存以索引和分片的形式保留在节点上。部分挂载的分片只会分配在 Frozen 层。因此集群中 Frozen 层节点不存储快照数据,只存储索引分片的元数据信息,原始数据存储在COS 的快照仓库中。
如下 API 样例所示,其中 storage 就是索引的挂载类型:full_copy 是全量挂载,而 shared_cache 则为部分挂载。
POST _snapshot/ss_repository/ss_daemonyue/_mount?wait_for_completion=true&storage=full_copy
{
"index": "daemonyue-2023.06.01-000001",
"renamed_index": "daemonyue-2023.06.01-000001_from_cos",
"index_settings": {
"index.number_of_replicas": 0
},
"ignore_index_settings": [ "index.refresh_interval" ]
}
POST _snapshot/ss_repository/ss_daemonyue/_mount?wait_for_completion=true&storage=shared_cache
{
"index": "daemonyue-2023.06.01-000001",
"renamed_index": "daemonyue-2023.06.01-000001_from_cos",
"index_settings": {
"index.number_of_replicas": 0
},
"ignore_index_settings": [ "index.refresh_interval" ]
}
Frozen 节点上的数据查询速度比全量挂载或普通索引慢很多,为了解决这个问题,Elasticsearch 提供了 Async Search(异步搜索)API,该 API 在执行时不会立即返回查询结果,而是返回一个请求 ID,随后异步准备数据。当数据准备就绪后,可以通过请求 ID 获取相应的数据。
POST sale*/_async_search?size=0
{
"sort": [
{ "date": { "order": "asc" } }
],
"aggs": {
"sale_date": {
"date_histogram": {
"field": "date",
"calendar_interval": "1d"
}
}
}
}
GET _async_search/status/{id} # 获取异步搜索的状态
GET _async_search/{id} # 获取异步搜索的执行结果
DELETE _async_search/{id} # 删除异步搜索
下面我们将演示可搜索快照实现的整条链路:
1)我们模拟业务持续向集群中写入数据,新生索引默认分布在热节点。索引配置了 rollover,在达到一定时间或一定大小后开始在热节点中滚动;
2)滚动完成后 7 天,开始迁移到冷节点上,并且执行 COS 备份;
3)备份完成后全量挂载(full_copy)到集群中,并删除集群中冷节点的索引;
4)全量挂载后 30 天,再将索引转为部分挂载(shared_cache),索引分片最终分配在冻结层。
首先我们使用腾讯云 COS 作为 ES 的快照仓库,仓库的名称为 ss_repository,同时指定了仓库路径为 searchable-snapshot。
仓库请求的完整API:
POST _snapshot/ss_repository
{
"type": "cos",
"settings": {
"app_id": "1253240642",
"access_key_id": "XXXXXn46uTmrhHdkbDm7C3f1XxxxXXxxxxxx",
"access_key_secret": "XXXXXFAtMYWFjxveGmIekaXxxxXxXXXx",
"bucket": "es-cos-dy",
"region": "ap-guangzhou",
"compress": true,
"chunk_size": "500mb",
"base_path": "searchable-snapshot"
}
}
配置ILM的目的是为了实现索引生命周期的自动化,其中包括:
下面的索引生命周期(ILM)API中,我们分别定义了索引的 hot / cold / frozen 三个阶段。
PUT _ilm/policy/ilm-ss
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_primary_shard_size": "10gb"
},
"set_priority": {
"priority": 100
}
}
},
"cold": {
"min_age": "7d",
"actions": {
"searchable_snapshot": {
"snapshot_repository": "ss_repository",
"force_merge_index": true
},
"set_priority": {
"priority": 0
},
"allocate": {
"number_of_replicas": 0
}
}
},
"frozen": {
"min_age": "30d",
"actions": {
"searchable_snapshot": {
"snapshot_repository": "ss_repository",
"force_merge_index": true
}
}
}
}
}
}
可视化配置索引生命周期(热阶段)
除了API,kibana 也提供可视化配置 ILM。下面展示的为热阶段(滚动阶段)的ILM策略。
我们关闭了默推荐的滚动策略,并且希望数据在写入的过程,当分片大小达到 20gb 或者当索引存在的时间达到 1 天时,索引发生滚动,生成一个新的索引,这样就可以控制单个索引的数据规模在一个可控范围内。
可视化配置索引生命周期(冷阶段)
在冷阶段我们开启了全量挂载( full mount ),选择了前面创建好的快照仓库,定义了冷阶段的触发时间,并调整了冷阶段的索引副本为 0。该阶段会将数据先备份到 COS 仓库,然后将快照索引全量挂载到冷节点并切换别名,最后删除热索引。
可视化配置索引生命周期(冷冻阶段)
冷冻阶段只需配置快照仓库和触发时间即可,该阶段会将快照索引部分挂载到冷冻层并切换别名,然后删除冷索引。
值得注意的是,部分挂载( partial mount)只会先保存索引的元数据相关信息,当查询冷冻数据时,ES会从快照中读取数据返回给客户端,并将查询缓存保存在冷冻层,用于加速查询。ES 有缓存淘汰策略,会定期清理不经常查询的缓存数据以释放空间。
ILM配置完成之后,还需要配置索引模板。
模版名称为 ss_template,在索引模版中定义了匹配模式为 "ss-*" 开头的索引,并指定刚才我们创建好的 ILM 策略(ilm-ss)以及索引 rollover 的别名(ss)。
另外还配置了分片分配策略( data_hot ),索引的刷新落盘间隔(30s),索引的分片数量(3),以及索引的副本数(1)。
PUT _template/ss_template
{
"order": 100,
"index_patterns": [
"ss-*"
],
"settings": {
"index": {
"lifecycle": {
"name": "ilm-ss",
"rollover_alias": "ss"
},
"routing": {
"allocation": {
"include": {
"_tier_preference": "data_hot"
}
}
},
"refresh_interval": "30s",
"number_of_shards": "3",
"number_of_replicas": "1"
}
}
}
可视化配置索引模板
索引模板也可以通过 kibana 可视化配置:
ILM 和 索引模板配置完成之后,我们就可以创建初始索引了,使用 <now+8h> 可以在索引名称里加上日期。索引创建完成后索引名称上包含了当前的日期,且后缀从标准的 rollover 000001 开始,索引的分片为3,副本为1。
PUT <ss-{now+8h}-000001>
{
"aliases": {
"ss": {
"is_write_index": true
}
}
}
索引有 7 个字段,分别为:
当热数据达到 rollover 条件之后,滚动后的历史索引会进入下一个阶段:cold / full mount。
这个阶段会先将热数据进行快照,当快照完成之后,ES会新建一个 restored- 开头的冷索引,并将快照全量挂载在这个索引上,然后删除热索引。整个过程采用的是别名替换的方式,做到业务的平滑切换无感知。
冷数据层数据如下,full mount 冷数据阶段会自动生成前缀为 restored- 的冷索引。
当热数据达到 cold 条件之后,降冷后的历史索引会进入下一个阶段:frozen / partial mount。
下面为索引进入到冷冻状态的展示,partial mount 冷冻阶段会自动生成前缀为 partial- 的冷索引。
热阶段 -> 冷阶段 -> 冷冻阶段,我们走完了索引 ILM 的一生。
接下来我们使用 DSL 查询语句来对数据进行检索,分别比较一下热数据和冷冻数据的查询性能。
我们以下面这条 DSL 为例,分别对热索引和冷冻索引进行查询,并做一个简单的count聚合。
POST ss-2023.06.09-000010/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "Joanne Smith"
}
},
{
"range": {
"age": {
"gte": 37
}
}
},
{
"match": {
"gender": "male"
}
},
{
"match": {
"job": "Ship broker"
}
}
],
"should": [
{
"match": {
"address": "4985 Patterson Streets"
}
},
{
"match": {
"description": "Government question white list"
}
}
]
}
},
"_source": [
"name",
"age",
"gender",
"job",
"description"
],
"aggs": {
"name_counts": {
"terms": {
"field": "name"
}
}
}
}
热数据查询耗时为 547ms
冷冻数据查询耗时为 2733ms
通过前面的 DSL 查询测试,可以看出热数据和冷冻数据的性能差距还是比较大的。主要的差距在于构建缓存的时间,当冷冻数据完成缓存构建之后,可以和热节点一样提供毫秒级查询。
我们也可以使用 kibana discover 来对数据进行检索,可以更直观的展示数据。
1、如何区分普通索引和可搜索快照索引?
答:使用 ILM 实现的可搜索快照,可以通过索引名称区分,前缀为 restored- 的索引为冷快照索引,前缀为 partial- 的索引为冷冻快照索引。
2、如果冷冻数据发生频繁查询,frozen 节点的磁盘会不会不够存储?
答:可搜索快照的缓存策略有自动淘汰机制,当缓存区空间不足时,会淘汰最近最少使用的缓存,另外可搜索快照的缓存状态也支持手动查看以及手动清理。
3、如果节点因为 OOM 或者机器宕机等原因发生重启,服务重新上线后,可搜索快照需要人工干预重新挂载吗?
答:节点重启上线后,可搜索快照也会像普通索引一样正常恢复,无需人工干预。
4、可搜索快照冷冻层的存储介质会影响查询效率吗?
答:对于冷冻层的磁盘,推荐使用 SSD,可以加速查询。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。