本文描述问题及解决方法适用于 腾讯云 Elasticsearch Service(ES)。
随着互联网技术的蓬勃发展,我们面临着日益复杂的海量数据。在这种背景下,用于全文搜索和大数据分析的 Elasticsearch 成为了开发者们解决这一问题的首选。然而,面对如此强大的功能,很多用户会陷入误区,忽略了 Elasticsearch 本身也需要优化的现实。本篇博客将结合工作经验,详细介绍 Elasticsearch 优化的一些实用技巧,为您的 Elasticsearch 实战之旅提供有力支持。
在不涉及高速缓存时,最小查询延迟取决于数据、查询类型、分片大小。查询大量小分片,虽然单个分片速度快,但是更多的查询任务排队处理,导致不一定比更大的分片快。 分片过大,会导致单个分片耗时过多。
不合理的后果:
ES 每个分片的本质是一个Lucene索引,会消耗相应的文件句柄,内存和CPU资源。 分片少时,单个节点的分片数有限,同节点资源竞争的问题不大,Lucene本身的资源消耗也不大。 但当分片数过大时,单个节点资源竞争的情况会加剧,容易导致节点响应超时,影响整个集群的响应。 从ES实际运维经验来看,控制在3万以内较安全。
ES版本在5.x/6.x时,还支持单index多个type。 但从6.8.2版本开始,单个index只支持一个type,默认_doc。 从7.x开始,不建议使用type,如果集群日志会提示type废弃。 从8.x开始,完全禁用type的使用。 因此为了以后进行集群升级的方便,应该在ES早期 版本应规避多type的使用。
当启用dynamic mapping时,如果写入的记录中带有新的field,会触发mapping更新。 以tsf集群为例,由于业务中引入新field,导致集群不停更新mapping,集群压力大,导致mapping 更新超时,集群red,写入跌0 建议将dynamic设置为strict。
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时,需要做好定期切换的计划。写入不大的情况下,建议按天、月滚动。 定期滚动的好处:
Bulk size的合适与否对集群写入性能影响较大。一般建议在1万上下浮动,单次请求控制在10~15MB左右。 单个集群短时间内能承受的最大写入并发数: num_of_node * bulk_queue_size
ES作为一款大数据产品,存放的数据量都在几十~上百T以上,且为了满足近实时的查询性能,往往都需要SSD作为存储,因此存储成本较高。为了尽量节约存储成本的开销,建议开启best-compression压缩。
5.X之后,String被分成两种类型,text和keyword。 二者区别: text:适用分词全文检索场景 keyword:适用字符串的精准匹配场景 实战中,通常面临:
是否需要精准匹配,即是否保留keyword 默认:
{
"foo":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
}
}
在Lucene中,文档存储在segment中,后台的ES通常在以下两种模式下连续维护Lucene段:
多层嵌套查询,会消耗比较大的CPU、内存,尤其是接收查询的协调节点,会有较高的CPU和内存压力,极端情况下,会导致节点old gc,请求超时,影响整个集群的响应。从目前线上的经验来看,单次聚合查询,一般100w分桶消耗在10GB内存左右。线上16C64G规格集群,建议控制聚合查询在3层嵌套100w分桶以下。
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提供了ES预处理的能力,类似于MySQL的SP,但是过多的pipeline使用,会增大es集群元数据管理的压力,消耗ES有限的计算资源。 建议将pipeline的要完成的工作,在程序端,或借助logstash等预处理工具,提前处理好,再写入ES,让ES专注于最核心的存储和搜索。类似于大家在使用MySQL时,要避免使用SP一样。 以TSF业务的为例: 业务在设计时,为每个用户自动创建一个pipeline,导致集群产生几千个pipeline任务,导致集群频繁的进行大规模元数据更新,且在升级6.8.x时,触发了pipeline遍历更新的bug。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。