Elasticsearch 优化锦囊

2023-11-06 20:15:50 浏览数 (1)

说明

本文描述问题及解决方法适用于 腾讯云 Elasticsearch Service(ES)

背景

随着互联网技术的蓬勃发展,我们面临着日益复杂的海量数据。在这种背景下,用于全文搜索和大数据分析的 Elasticsearch 成为了开发者们解决这一问题的首选。然而,面对如此强大的功能,很多用户会陷入误区,忽略了 Elasticsearch 本身也需要优化的现实。本篇博客将结合工作经验,详细介绍 Elasticsearch 优化的一些实用技巧,为您的 Elasticsearch 实战之旅提供有力支持。

一、单个分片大小控制在30GB左右

在不涉及高速缓存时,最小查询延迟取决于数据、查询类型、分片大小。查询大量小分片,虽然单个分片速度快,但是更多的查询任务排队处理,导致不一定比更大的分片快。 分片过大,会导致单个分片耗时过多。

不合理的后果:

  • 单个节点磁盘占用过多,或单块磁盘占用过多,资源浪费。
  • 影响集群查询性能

二、集群总分片数控制在3万以内

ES 每个分片的本质是一个Lucene索引,会消耗相应的文件句柄,内存和CPU资源。 分片少时,单个节点的分片数有限,同节点资源竞争的问题不大,Lucene本身的资源消耗也不大。 但当分片数过大时,单个节点资源竞争的情况会加剧,容易导致节点响应超时,影响整个集群的响应。 从ES实际运维经验来看,控制在3万以内较安全。

三、不要在单个index使用多个type

ES版本在5.x/6.x时,还支持单index多个type。 但从6.8.2版本开始,单个index只支持一个type,默认_doc。 从7.x开始,不建议使用type,如果集群日志会提示type废弃。 从8.x开始,完全禁用type的使用。 因此为了以后进行集群升级的方便,应该在ES早期 版本应规避多type的使用。

四、避免使用dynamic mapping

当启用dynamic mapping时,如果写入的记录中带有新的field,会触发mapping更新。 以tsf集群为例,由于业务中引入新field,导致集群不停更新mapping,集群压力大,导致mapping 更新超时,集群red,写入跌0 建议将dynamic设置为strict。

五、控制单shard的docs数不超过21亿

ES对于单个shard的docs数有21亿的限制,上线index前,提前预估好每个shard的分片数,建议控制在15亿以内。 Per_shard_docs = index_total_docs/number_of_shard

六、查询中提供明确的超时

几乎所有的elasticsearch api都允许用户指定超时。 提前终止耗时长的操作,避免正常请求受到牵连,对于节省系统资源,建立稳定的ES服务,有很大的帮助。 以tsf业务为例: 一条复杂查询请求,由于没有超时设计,导致ctsdb整个集群持续old gc,服务不可用,集群所有读写跌0。

七、不要长期使用单个index,必须定期滚动

使用index时,需要做好定期切换的计划。写入不大的情况下,建议按天、月滚动。 定期滚动的好处:

  • 控制单个index的大小,提升读写性能。
  • 防止单个index过大,影响故障恢复的时间。
  • 避免热index过大,影响cos备份恢复时间。

八、合理设置bulk size大小

Bulk size的合适与否对集群写入性能影响较大。一般建议在1万上下浮动,单次请求控制在10~15MB左右。 单个集群短时间内能承受的最大写入并发数: num_of_node * bulk_queue_size

九、对于写少存多的业务,开启Best_compression压缩

ES作为一款大数据产品,存放的数据量都在几十~上百T以上,且为了满足近实时的查询性能,往往都需要SSD作为存储,因此存储成本较高。为了尽量节约存储成本的开销,建议开启best-compression压缩。

十、合理设置string类型

5.X之后,String被分成两种类型,text和keyword。 二者区别: text:适用分词全文检索场景 keyword:适用字符串的精准匹配场景 实战中,通常面临:

  • 需不需要分词,不需要,则仅保留keyword即可。
  • 需要用什么分词,英文分词还是中文分词。
  • 分词后是否需要排序和聚合,即fielddata是否需要打开。

是否需要精准匹配,即是否保留keyword 默认:

代码语言:javascript复制
{
    "foo":{
        "type":"text",
        "fields":{
            "keyword":{
                "type":"keyword",
                "ignore_above":256
            }
        }
    }
}

十一、合理控制段合并

在Lucene中,文档存储在segment中,后台的ES通常在以下两种模式下连续维护Lucene段:

  • 当删除或更新文档时,旧文档被标记为已删除,新文档被创建,ES会跟踪这些标记为delete的文档,适时对其进行合并。
  • 新添加的文档可能会产生大小不平衡的段。ES可能出于优化目的而决定将它们合并为更大的段。 段合并是高度受磁盘IO和CPU约束的操作。 找到translog flush的最优配置。通过尝试调整index.translog.sync_interval和index.translog.flush_threshold_size的设置。 对于实时性要求不高的场景,可以调大刷新频率。(refresh_interval,官方默认1s,CES默认5s,可以适当调到30s甚 至更大)

十二、规避过度聚合查询

多层嵌套查询,会消耗比较大的CPU、内存,尤其是接收查询的协调节点,会有较高的CPU和内存压力,极端情况下,会导致节点old gc,请求超时,影响整个集群的响应。从目前线上的经验来看,单次聚合查询,一般100w分桶消耗在10GB内存左右。线上16C64G规格集群,建议控制聚合查询在3层嵌套100w分桶以下。

十三、正确理解模版order属性

ES的模版中,适用于相同index的模版,会按照order顺序,从低到高,逐级生效。高order模版会覆盖之前低order模版的相同设置。 假如有匹配logstash-*, 且order为1、2、3的三个template, number_of_shards设置依次为1、2、3,那么业务写入一个logstash@2020-8-19的index时,生成的index,将有3个主分片。 Ps:CES在每个集群中会有一个默认的order为0的 default@template模版,务必不要删除该模版,否则会影响一些OSS的管控操作。

十四、善用别名

善于使用别名的好处:

  • 应用与索引名称的解藕。
  • 方便的实现跨索引检索。
  • 索引变换期间,零停服

十五、避免过度使用Pipeline

Pipeline提供了ES预处理的能力,类似于MySQL的SP,但是过多的pipeline使用,会增大es集群元数据管理的压力,消耗ES有限的计算资源。 建议将pipeline的要完成的工作,在程序端,或借助logstash等预处理工具,提前处理好,再写入ES,让ES专注于最核心的存储和搜索。类似于大家在使用MySQL时,要避免使用SP一样。 以TSF业务的为例: 业务在设计时,为每个用户自动创建一个pipeline,导致集群产生几千个pipeline任务,导致集群频繁的进行大规模元数据更新,且在升级6.8.x时,触发了pipeline遍历更新的bug。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞