配置OpenSearch集群存算分离
存算分离支持将集群新写入的数据存储在SSD来达到最佳的查询检索性能,将历史数据存储到OBS中降低数据的存储成本。
场景描述
存算分离是通过冻结索引将历史数据转储到OBS,以此降低数据的存储成本。
对于有海量数据写入和存储的场景,数据有明显的冷热区分,新写入的数据一般属于热数据,存储在SSD中方便快速被搜索,随着时间的推移,历史数据不再写入,查询QPS也降低,这时候历史数据就算冷数据,通过存算分离将冷数据转储到OBS,热数据依旧存放在SSD中,方便快速搜索。
本文通过Kibana访问集群,介绍如何使用存算分离。
约束限制
- 仅Elasticsearch 7.6.2、Elasticsearch 7.10.2、OpenSearch 1.3.6集群支持存算分离。
- 在执行冻结索引前,系统会将待冻结的索引配置为只读状态,即便在索引数据转储到OBS后,索引也是只读状态,不支持写入数据。
- 在冻结索引过程中,查询请求不受影响。在冻结完成后,会将索引先Close再Open,在这段时间内,索引不可查询,集群可能短暂出现Red状态,索引Open结束后集群恢复正常。
- 将历史索引数据转储到OBS的过程中会占用网络带宽。
- 冻结索引后,索引会被转储到OBS中,同时本地磁盘中的索引数据会被删除。当查询被冻结的索引时,时延会增加,在聚合时,由于查询复杂、数据读取多,时延变长会更明显。
- 已转储到OBS中的索引不支持解冻,即不可回退为可写的索引。
- 由于存算分离的特性依赖OBS,所以使用过程中要遵守OBS的“带宽”和“每秒请求数(QPS)”的使用限制,详细请参见OBS使用限制。当超过限制时,集群中涉及到OBS查询的性能都会下降,例如恢复分片的速度变慢、查询数据时变慢等。
访问集群
- 登录云搜索服务管理控制台。
- 在“集群管理”页面,选择需要访问的集群,单击操作列“Kibana”,登录Kibana页面。
- 选择左侧导航栏的“Dev Tools”,进入操作页面。
冻结索引
POST ${index_name}/_freeze_low_cost
参数名 |
说明 |
---|---|
index_name |
需要冻结的索引名称。 |
返回结果如下:
{ "freeze_uuid": "pdsRgUtSTymVDWR_HoTGFw" }
参数名 |
说明 |
---|---|
freeze_uuid |
冻结索引任务的ID,在提交冻结请求后会启动一个异步任务,请求返回任务ID,使用该ID可以查询冻结索引任务的进度。 |
查看冻结索引任务
GET _freeze_low_cost_progress/${freeze_uuid}
参数名 |
说明 |
---|---|
freeze_uuid |
冻结索引任务的ID,该ID由冻结索引时获取。 |
返回结果如下:
{ "stage" : "STARTED", "shards_stats" : { "INIT" : 0, "FAILURE" : 0, "DONE" : 0, "STARTED" : 3, "ABORTED" : 0 }, "indices" : { "data1" : [ { "uuid" : "7OS-G1-tRke2jHZPlckexg", "index" : { "name" : "data1", "index_id" : "4b5PHXJITLaS6AurImfQ9A", "shard" : 2 }, "start_ms" : 1611972010852, "end_ms" : -1, "total_time" : "10.5s", "total_time_in_millis" : 10505, "stage" : "STARTED", "failure" : null, "size" : { "total_bytes" : 3211446689, "finished_bytes" : 222491269, "percent" : "6.0%" }, "file" : { "total_files" : 271, "finished_files" : 12, "percent" : "4.0%" }, "rate_limit" : { "paused_times" : 1, "paused_nanos" : 946460970 } }, { "uuid" : "7OS-G1-tRke2jHZPlckexg", "index" : { "name" : "data1", "index_id" : "4b5PHXJITLaS6AurImfQ9A", "shard" : 0 }, "start_ms" : 1611972010998, "end_ms" : -1, "total_time" : "10.3s", "total_time_in_millis" : 10359, "stage" : "STARTED", "failure" : null, "size" : { "total_bytes" : 3221418186, "finished_bytes" : 272347118, "percent" : "8.0%" }, "file" : { "total_files" : 372, "finished_files" : 16, "percent" : "4.0%" }, "rate_limit" : { "paused_times" : 5, "paused_nanos" : 8269016764 } }, { "uuid" : "7OS-G1-tRke2jHZPlckexg", "index" : { "name" : "data1", "index_id" : "4b5PHXJITLaS6AurImfQ9A", "shard" : 1 }, "start_ms" : 1611972011021, "end_ms" : -1, "total_time" : "10.3s", "total_time_in_millis" : 10336, "stage" : "STARTED", "failure" : null, "size" : { "total_bytes" : 3220787498, "finished_bytes" : 305789614, "percent" : "9.0%" }, "file" : { "total_files" : 323, "finished_files" : 14, "percent" : "4.0%" }, "rate_limit" : { "paused_times" : 3, "paused_nanos" : 6057933087 } } ] } }
参数名 |
说明 |
---|---|
stage |
当前所处状态。取值包括:
|
shards_stats |
处在各个状态的shard个数。 |
indices |
每个索引的状态详情。 |
参数名 |
说明 |
---|---|
uuid |
freeze的uuid。 |
index |
索引信息和shard信息。 |
start_ms |
开始时间。 |
end_ms |
结束时间,如果没有结束则显示为-1。 |
total_time |
已花费时间。 |
total_time_in_millis |
已花费时间毫秒数。 |
stage |
当前shard所处的状态。 |
failure |
失败原因,如果没有失败则显示为null。 |
size.total_bytes |
总共需要冻结的文件的字节数。 |
size.finished_bytes |
已经完成冻结的字节数。 |
size.percent |
已经完成冻结的字节数百分比。 |
file.total_bytes |
总共需要冻结的文件个数。 |
file.finished_bytes |
已经完成冻结的文件个数。 |
file.percent |
已经完成冻结的文件个数百分比。 |
rate_limit.paused_times |
达到限速导致冻结暂停的次数。 |
rate_limit.paused_nanos |
达到限速导致冻结暂停的时间纳秒数。 |
冻结完成的索引会增加以下settings,可参考表6。
基于冻结状态查询索引列表
GET _cat/freeze_indices?stage=${STAGE}
参数名 |
说明 |
---|---|
STAGE |
索引的冻结状态,可选值如下:
|
返回结果如下:
green open data2 0bNtxWDtRbOSkS4JYaUgMQ 3 0 5 0 7.9kb 7.9kb green open data3 oYMLvw31QnyasqUNuyP6RA 3 0 51 0 23.5kb 23.5kb
此命令的参数和返回值与开源Elasticsearch的_cat/indices一致。
修改存储在OBS中冷数据的缓存配置
索引数据转储到OBS后,为了尽可能的减少对OBS的访问请求,并提升集群的查询性能,系统会缓存部分数据。第一次查询冷数据时,集群会直接访问OBS,获取到的数据会被缓存在集群内存中,后续查询时会先检查是否有缓存数据。
集群访问不同的文件,访问的模式是不一样的,缓存系统支持多级缓存,会使用不同大小的block来缓存不同的文件,例如fdx和tip文件会使用大量的小block缓存,对fdt文件会使用较少的大block缓存。缓存配置支持基于业务情况进行修改,配置项请参见表8。
配置项 |
类型 |
说明 |
---|---|---|
low_cost.obs.blockcache.names |
Array |
缓存系统支持多级缓存,分别用来缓存不同访问粒度的数据。此配置列出所有缓存的名字,即使不配置,系统也会默认有一个缓存,名字为default。如果自定义配置,请确保有一个名字为default的缓存,其他名字任意。 默认值:default。 |
low_cost.obs.blockcache.<NAME>.type |
ENUM |
缓存的类型,支持memory和file。 当使用memory类型的缓存时,会占用一定的内存大小。当使用file类型的缓存时,会使用磁盘作为缓存。建议使用超高IO型的磁盘提升缓存性能。 默认值:memory。 |
low_cost.obs.blockcache.<NAME>.blockshift |
Integer |
缓存每个block的大小,为字节左移数,即2x字节。如配置为16,表示block大小为216字节,等于65536字节,即64K。 默认值:13(即8K)。 |
low_cost.obs.blockcache.<NAME>.bank.count |
Integer |
缓存分区数。 默认值:1。 |
low_cost.obs.blockcache.<NAME>.number.blocks.perbank |
Integer |
每个缓存分区中包含的block数。 默认值:8192。 |
low_cost.obs.blockcache. <NAME>.exclude.file.types |
Array |
不缓存的文件后缀名。如果某些后缀既不包含在exclude列表,也不包含在include列表,则会使用default缓存。 |
low_cost.obs.blockcache. <NAME>.file.types |
Array |
缓存的文件后缀名。如果某些后缀既不包含在exclude列表,也不包含在include列表,则会使用default缓存。 |
index.frozen.obs.max_bytes_per_sec |
String |
冻结过程中往OBS上传文件最大限速。动态配置,修改后立即生效。 默认值:150MB。 |
low_cost.obs.index.upload.threshold.use.multipart |
String |
冻结过程中文件大小超过此配置会使用OBS的分段上传。 默认值:1GB。 |
index.frozen.reader.cache.expire.duration.seconds |
Integer |
此参数设置超时时间。 为了减少冻结后的索引占用的堆内存,在索引shard启动后,reader会缓存一段时间,超时后关闭。 默认值:300s。 |
index.frozen.reader.cache.max.size |
Integer |
配置缓存最大值。 默认值:100。 |
下面是一个常见的缓存配置,该配置使用两级缓存,名字分别为“default”和“large”。其中,“default”缓存使用大小为64K的block,一共有30*4096个block,“default”缓存用于缓存除fdt后缀的其他文件,“large”缓存使用大小为2M的block,一共有5*1000个block,“large”缓存用于缓存fdx、dvd和tip后缀的文件。
low_cost.obs.blockcache.names: ["default", "large"] low_cost.obs.blockcache.default.type: file low_cost.obs.blockcache.default.blockshift: 16 low_cost.obs.blockcache.default.number.blocks.perbank: 4096 low_cost.obs.blockcache.default.bank.count: 30 low_cost.obs.blockcache.default.exclude.file.types: ["fdt"] low_cost.obs.blockcache.large.type: file low_cost.obs.blockcache.large.blockshift: 21 low_cost.obs.blockcache.large.number.blocks.perbank: 1000 low_cost.obs.blockcache.large.bank.count: 5 low_cost.obs.blockcache.large.file.types: ["fdx", "dvd", "tip"]
查询存储在OBS中冷数据的缓存状态
冻结索引之后,当冷数据第一次被查询时,系统会自动进行数据缓存,集群支持查询存储在OBS中冷数据的缓存状态。当需要调试集群性能时,也可以重置缓存状态。
- 查询节点中存储在OBS中冷数据的缓存状态。
- 执行如下命令,查询所有节点中冷数据的缓存信息。
GET _frozen_stats
- 执行如下命令,查询指定节点中冷数据的缓存信息。
GET _frozen_stats/${node_id}
表9 请求参数说明 参数名
说明
node_id
节点ID。
返回结果如下:
{ "_nodes" : { "total" : 3, // 所有节点数量 "successful" : 3, // 成功的节点数量 "failed" : 0 // 失败的节点数量 }, "cluster_name" : "css-zzz1", // 集群名称 "nodes" : { "7uwKO38RRoaON37YsXhCYw" : { "name" : "css-zzz1-ess-esn-2-1", // 节点名称 "transport_address" : "10.0.0.247:9300", // 节点transport连接地址 "host" : "10.0.0.247", // 节点host "ip" : "10.0.0.247", // 节点IP "block_cache" : { "default" : { "type" : "memory", // cache类型,memory表示内存cache "block_cache_capacity" : 8192, // cache容量 "block_cache_blocksize" : 8192, // cache中单个block大小,单位为bytes,如此处表示8k "block_cache_size" : 12, // cache已被占用的大小 "block_cache_hit" : 14, // cache命中数 "block_cache_miss" : 0, // cache未命中数 "block_cache_eviction" : 0, // cache被逐出次数 "block_cache_store_fail" : 0 // 如果cache满了,可能导致新的cache存储失败,此处表示存储失败的次数 } }, "obs_stats" : { "list" : { "obs_list_count" : 17, // 调用OBS list接口的次数 "obs_list_ms" : 265, // 调用OBS list接口的总耗时 "obs_list_avg_ms" : 15 // 调用OBS list接口的平均耗时 }, "get_meta" : { "obs_get_meta_count" : 79, // 调用OBS 获取元数据接口的次数 "obs_get_meta_ms" : 183, // 调用OBS 获取元数据接口的总耗时 "obs_get_meta_avg_ms" : 2 // 调用OBS 获取元数据接口的平均耗时 }, "get_obj" : { "obs_get_obj_count" : 12, // 调用OBS getObject接口的次数 "obs_get_obj_ms" : 123, // 调用OBS getObject接口的总耗时 "obs_get_obj_avg_ms" : 10 // 调用OBS getObject接口的平均耗时 }, "put_obj" : { "obs_put_obj_count" : 12, // 调用OBS putObject接口的总次数 "obs_put_obj_ms" : 2451, // 调用OBS putObject接口的总耗时 "obs_put_obj_avg_ms" : 204 // 调用OBS putObject接口的平均耗时 }, "obs_op_total" : { "obs_op_total_ms" : 3022, // 调用OBS接口的总耗时 "obs_op_total_count" : 120, // 调用OBS接口的总次数 "obs_op_avg_ms" : 25 // 调用OBS接口的平均耗时 } }, "reader_cache" : { "hit_count" : 0, "miss_count" : 1, "load_success_count" : 1, "load_exception_count" : 0, "total_load_time" : 291194714, "eviction_count" : 0 } }, "73EDpEqoQES749umJqxOzQ" : { "name" : "css-zzz1-ess-esn-3-1", "transport_address" : "10.0.0.201:9300", "host" : "10.0.0.201", "ip" : "10.0.0.201", "block_cache" : { "default" : { "type" : "memory", "block_cache_capacity" : 8192, "block_cache_blocksize" : 8192, "block_cache_size" : 12, "block_cache_hit" : 14, "block_cache_miss" : 0, "block_cache_eviction" : 0, "block_cache_store_fail" : 0 } }, "obs_stats" : { "list" : { "obs_list_count" : 17, "obs_list_ms" : 309, "obs_list_avg_ms" : 18 }, "get_meta" : { "obs_get_meta_count" : 79, "obs_get_meta_ms" : 216, "obs_get_meta_avg_ms" : 2 }, "get_obj" : { "obs_get_obj_count" : 12, "obs_get_obj_ms" : 140, "obs_get_obj_avg_ms" : 11 }, "put_obj" : { "obs_put_obj_count" : 12, "obs_put_obj_ms" : 1081, "obs_put_obj_avg_ms" : 90 }, "obs_op_total" : { "obs_op_total_ms" : 1746, "obs_op_total_count" : 120, "obs_op_avg_ms" : 14 } }, "reader_cache" : { "hit_count" : 0, "miss_count" : 1, "load_success_count" : 1, "load_exception_count" : 0, "total_load_time" : 367179751, "eviction_count" : 0 } }, "EF8WoLCUQbqJl1Pkqo9-OA" : { "name" : "css-zzz1-ess-esn-1-1", "transport_address" : "10.0.0.18:9300", "host" : "10.0.0.18", "ip" : "10.0.0.18", "block_cache" : { "default" : { "type" : "memory", "block_cache_capacity" : 8192, "block_cache_blocksize" : 8192, "block_cache_size" : 12, "block_cache_hit" : 14, "block_cache_miss" : 0, "block_cache_eviction" : 0, "block_cache_store_fail" : 0 } }, "obs_stats" : { "list" : { "obs_list_count" : 17, "obs_list_ms" : 220, "obs_list_avg_ms" : 12 }, "get_meta" : { "obs_get_meta_count" : 79, "obs_get_meta_ms" : 139, "obs_get_meta_avg_ms" : 1 }, "get_obj" : { "obs_get_obj_count" : 12, "obs_get_obj_ms" : 82, "obs_get_obj_avg_ms" : 6 }, "put_obj" : { "obs_put_obj_count" : 12, "obs_put_obj_ms" : 879, "obs_put_obj_avg_ms" : 73 }, "obs_op_total" : { "obs_op_total_ms" : 1320, "obs_op_total_count" : 120, "obs_op_avg_ms" : 11 } }, "reader_cache" : { "hit_count" : 0, "miss_count" : 1, "load_success_count" : 1, "load_exception_count" : 0, "total_load_time" : 235706838, "eviction_count" : 0 } } } }
- 执行如下命令,查询所有节点中冷数据的缓存信息。
- 执行如下命令,可以重置缓存状态。
POST _frozen_stats/reset
此命令主要用于调试性能问题,例如重置缓存状态后再次执行查询可以清晰看到本次查询的缓存命令情况。在业务运行阶段不需要执行此命令。
返回结果如下:
{ "_nodes" : { "total" : 1, "successful" : 1, "failed" : 0 }, "cluster_name" : "Es-0325-007_01", "nodes" : { "mqTdk2YRSPyOSXfesREFSg" : { "result" : "ok" } } }
提升冷数据的查询性能
仅2023年02月后创建的Elasticsearch 7.6.2、Elasticsearch 7.10.2和OpenSearch 1.3.6集群支持提升冷数据的查询性能。
在Kibana的Discover页面首次查询冷数据时,由于此时无任何缓存,导致所有数据均需要从OBS上获取,当命中的数据较多时,需要耗费大量的时间从OBS上获取对应的时间字段以及文件元数据。如果将这一部分数据直接缓存在本地,即可大幅提升查询性能,解决Discover页面首次查询慢的问题。云搜索服务就是通过冷数据的本地缓存,实现冷数据的查询性能提升。本地缓存配置是预置的,用户可以基于业务场景修改配置,也可以查询、了解本地缓存信息。
- 修改冷数据的本地缓存配置。
表10 本地缓存配置项说明 配置项
类型
scope
是否可动态修改
说明
low_cost.local_cache.max.capacity
Integer
node
是
节点上,能够打开的冷数据缓存的最大数量。(每个shard对应一个缓存对象)
取值范围:10~5000
默认值:500
说明:- 当堆内存使用率一直很高时,可以尝试降低该值。
- 当查询冷数据本地缓存的相关统计指标中load_overflow_count数值一直持续快速增加时,建议调大该值。
index.low_cost.local_cache.threshold
Integer
index
是
启用冷数据本地缓存的阈值。
- 当date类型字段的占比小于此值时,启用冷数据本地缓存date类型字段。否则不使用。
- 如果当前索引的date类型字段占据当前索引的绝大部分数据量,则不建议使用此功能。
单位:%
取值范围:0~100
默认值:50
index.low_cost.local_cache.evict_time
字符串
index
是
冷数据的本地缓存的淘汰时间,当缓存时间大于该值,缓存将被删除。根据index.frozen_date(冻结成功的时间)判定,当索引无index.frozen_date时,则根据索引创建时间判定。
单位:天
取值范围:1d~365d
默认值:30d
说明:建议根据磁盘用量调整淘汰时长,节省磁盘空间。
- 执行如下命令,修改“low_cost.local_cache.max.capacity”。
PUT _cluster/settings { "persistent": { "low_cost.local_cache.max.capacity":1000 } }
- 执行如下命令,修改“index.low_cost.local_cache.threshold”。
PUT es_write_pref2-00000000021/_settings { "index.low_cost.local_cache.threshold":20 }
- 执行如下命令,修改“index.low_cost.local_cache.evict_time”。
PUT es_write_pref2-00000000021/_settings { "index.low_cost.local_cache.evict_time":"7d" }
- 查询冷数据的本地缓存信息。
- 执行如下命令,查询所有节点中冷数据的本地缓存相关指标。
GET /_frozen_stats/local_cache
- 执行如下命令,查询指定节点中冷数据的本地缓存相关指标。
GET /_frozen_stats/local_cache/{nodeId}
“{nodeId}”为节点ID。
返回结果如下:
{ "_nodes" : { "total" : 1, "successful" : 1, "failed" : 0 }, "cluster_name" : "elasticsearch", "nodes" : { "6by3lPy1R3m55Dcq3liK8Q" : { "name" : "node-1", "transport_address" : "127.0.0.1:9300", "host" : "127.0.0.1", "ip" : "127.0.0.1", "local_cache" : { "get_stats" : { "get_total_count" : 562, //从冷数据本地缓存查询数据的总次数 "get_hit_count" : 562, //从冷数据本地缓存查询数据命中的次数 "get_miss_count" : 0, //从冷数据本地缓存查询数据未命中的次数 "get_total_ns" : 43849200, //从冷数据本地缓存查询数据的总时长 "get_avg_ns" : 78023 //从冷数据本地缓存查询数据的平均时长 }, "load_stats" : { "load_count" : 2, //加载冷数据本地缓存的次数 "load_total_ms" : 29, //加载冷数据本地缓存的总时长 "load_avg_ms" : 14, //加载冷数据本地缓存的平均时长 "load_fail_count" : 0, //加载冷数据本地缓存的失败次数 "load_overflow_count" : 0 //加载冷数据本地缓存时超过缓存池的次数 }, "reload_stats" : { "reload_count" : 0, //重新生成冷数据本地缓存的次数 "reload_total_ms" : 0, //重新生成冷数据本地缓存的总时长 "reload_avg_ms" : 0, //重新生成冷数据本地缓存的平均时长 "reload_fail_count" : 0 //重新生成冷数据本地缓存的失败次数 }, "init_stats" : { "init_count" : 0, //初始化冷数据本地缓存的次数 "init_total_ms" : 0, //初始化冷数据本地缓存的总时长 "init_avg_ms" : 0, //初始化冷数据本地缓存的平均时长 "init_fail_count" : 0 //初始化冷数据本地缓存的失败次数 } } } } }
- 执行如下命令,查询所有节点中冷数据的本地缓存相关指标。
查询存储冷数据的OBS实时速率
仅2023年02月后创建的Elasticsearch 7.6.2、Elasticsearch 7.10.2和OpenSearch 1.3.6集群支持提升冷数据的查询性能。
为了更清晰的了解到存算分离的插件在OBS中的使用情况,CSS服务新增了OBS实时速率的统计接口,并且将实时速率记录到系统索引“.freeze_obs_rate-YYYY.mm.dd”中。
OBS实时速率的计算方式:每5秒计算一次,查询前5秒内的平均OBS操作速率。
系统索引“.freeze_obs_rate-YYYY.mm.dd”用于存放OBS操作实时速率和OBS操作数据,便于了解存储冷数据的OBS的操作趋势。该索引的默认保留时间是30天。
- 查询存储冷数据的OBS实时速率。
- 执行如下命令,查询所有节点中存储冷数据的OBS实时速率。
GET _frozen_stats/obs_rate
- 执行如下命令,查询指定节点中存储冷数据的OBS实时速率。
GET _frozen_stats/obs_rate/{nodeId}
“{nodeId}”为节点ID。
响应示例:{ "_nodes" : { "total" : 1, "successful" : 1, "failed" : 0 }, "cluster_name" : "elasticsearch", "nodes" : { "dflDvcSwTJ-fkiIlT2zE3A" : { "name" : "node-1", "transport_address" : "127.0.0.1:9300", "host" : "127.0.0.1", "ip" : "127.0.0.1", "update_time" : 1671777600482, // 当前统计值的更新时间。 "obs_rate" : { "list_op_rate" : 0.0, // obs list操作的速率,单位:次/秒。 "get_meta_op_rate" : 0.0, // obs get meta操作的速率,单位:次/秒。 "get_obj_op_rate" : 0.0, // obs get操作的速率,单位:次/秒。 "put_op_rate" : 0.0, // obs put操作的速率,单位:次/秒。 "obs_total_op_rate" : 0.0, // obs所有操作的速率,单位:次/秒。 "obs_upload_rate" : "0.0 MB/s", // obs上传数据的速率,MB/秒。 "obs_download_rate" : "0.0 MB/s" // obs下载数据的速率,MB/秒。 } } } }
- 执行如下命令,查询所有节点中存储冷数据的OBS实时速率。
- 修改存储OBS实时速率的索引“.freeze_obs_rate-YYYY.mm.dd”的保留时间。索引的默认保留时间是30天。
执行如下命令,将索引保留时间改成7天。
PUT _cluster/settings { "persistent": { "low_cost.obs_rate_index.evict_time": "7d" } }
表11 配置项说明 配置项
类型
scope
是否可动态修改
说明
low_cost.obs_rate_index.evict_time
String
node
是
用于控制索引“.freeze_obs_rate-YYYY.mm.dd”的保留时间。
- 取值范围:1d~365d。
- 默认值:30d。
- 单位:天。