ElasticSearch查询慢问题

Posted weixin_47541454

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch查询慢问题相关的知识,希望对你有一定的参考价值。

问题

【查询慢】从500ms左右升高至5s+拒绝服务

改进点

QPS不稳定 + ES的排队机制

会增加将请求保留在队列中的时间长度(如0.5s的处理时间+3.5s的排队时间),从而导致客户端超时重试加剧恶化(上一个请求还在排队,客户端发现超时又发起了新的请求)

解决方案:

  • 接入服务进行ES请求速率的控制,不提供es地址给业务方,避免滥用(一般无法控制,老板说给还是得给)
  • 查询量高的服务,可以适当调高 search 线程数量
  • 可以适当调低对列大小,快速失败而不是将业务已认定超时的请求还在排队等待处理,导致es一直恢复不了
索引分片数据量大小增加导致查询变慢

ES官方建议单分片20G-40G之间,最合适的大小应通过对业务数据进行基准测试来确定
ES索引的分片数量一定确定就无法更改,只能重建索引,若在原ES集群上建立新的索引会占用资源影响现有集群性能,一般只能进行集群迁移/集群扩容

解决方案:

  • 分片数量根据基准测试确定,同时根据业务数据增长特点预留一部分空间
  • 可以es索引模版功能自动扩展索引,保证每个分片大小都在20G-40G之间,可参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-templates.html
查询参数不合理(参考业务方使用es中出现过的问题)
  • 根据业务id查询时使用的es条件时query的terms类请求进行字段匹配,改成query的ids类请求
  • 应提前测好es查询能接受的qps,不要来多少查多少
未进行数据预热就上线

解决方案:

  • 捞取线上流量在上线前对ES进行预热,直到响应速度符合预期
  • 可设置 index.store.preload 指定文件类型预热
字段类型设置不合理

字符串字段默认为 text + keyword ,会进行分词增加开销

解决方案:

  • 若只对字符串字段进行等值匹配,将字段类型设置为 keyword
  • 可枚举的聚合字段标注 eager_global_ordinals ,用于减少内存占用 + 加快聚合速度
  • 不需要聚合和排序的字段标注 doc_values = false,不需要查询的字段标注 index = false
  • 不需要 score 的字段设置 norms = false
删除数据未及时清理
  • 必要时对索引执行 force_merge,可以零碎(包含标记删除的数据)的分片合并为一个大分段,可以提高检索效率
  • 定期合并清理删除数据可以避免写入速度小于合并速度时磁盘空间不断增加达到水位线出现拒绝写入的现象(官方并不建议自行合并
资源升级
  • 使用SSD磁盘
  • 扩容:除了花钱,在很多时候都是最简单有效又安全的办法(调参有风险+对维护人员要求高)

ES常见配置

  • index.refresh_interval 更新间隔,默认为1s,指的是创建新 segment 合并旧 segment 的周期,可以根据业务实时性要求修改,调大后可以减少 segment 合并的压力
  • indices.memory.index_buffer_size 默认10% 建立索引时使用,除refresh_interval以外生成新 segment 的机会(静态配置)
    es底层使用lucene来提供搜索能力,一个lucene的index是由许多独立的segment组成的。segment是最小的数据存储单元,其中包含了文档中的词汇字典、词汇字典的倒排索引以及Document的字段数据,提供搜索功能。es接受到一个数据数据不会马上就创建一个segment,一方面是耗时,一方面是产生巨量的segment会降低IO性能,因此es会将最近新增的数据缓存起来(indices.memory.index_buffer_size),每隔一段时间(index.refresh_interval )就生成一个segment,清空缓存数据,此时数据就可以被搜索。
  • index.translog.durability 如何同步translog到磁盘 默认是request(每次操作都fsync),async与sync_interval搭配使用
  • index.translog.sync_interval 默认5s,在业务对数据完整性要求(如业务日志)不高时,可以调高这个数值
  • index.translog.flush_threshold_size translog大小达到此值时flush,默认是512mb
  • index.translog.flush_threshold_period 在该时间内至少有一次flush,默认是30m

translog(事务日志),当es未生成segment时宕机时,数据就会发生丢失,为了保证可靠性,es引入translog,每次数据被添加或者删除,都会在translog中添加一条记录,这样一旦发生崩溃,数据可以从translog中恢复。

  • index.store.preload 文件系统缓存预热
  • indices.queries.cache.size 节点查询缓存配置,默认为10%,不需要缓存可以调低此数值节省内存空间
  • index.queries.cache.enabled 建立索引时不需要查询缓存可以关闭

ES常用URL

  • 查看当前执行任务 http://10.25.94.32:8200/_cat/tasks?detailed=true
  • 查看当前索引大小 http://10.25.94.32:8200/_cat/indices
  • 查看对列正在处理/排队/拒绝/已执行任务情况 http://10.25.94.32:8200/_cat/thread_pool?v&s=t,n&h=type,name,node_name,active,queue,rejected,completed

参考:
https://www.elastic.co/cn/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/preload-data-to-file-system-cache.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/doc-values.html#doc-value-only-fields
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-cache.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/indexing-buffer.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
https://www.elastic.co/cn/blog/elasticsearch-caching-deep-dive-boosting-query-speed-one-cache-at-a-time
https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html
https://blog.wangqi.love/articles/ElasticSearch/Elasticsearch%E2%80%94%E2%80%94Translog%E7%AE%80%E4%BB%8B.html

以上是关于ElasticSearch查询慢问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥在elasticsearch慢查询中take_millis和超时之间有很多时间成本

LOGSTASH+ELASTICSEARCH 处理 MYSQL 慢查询日志

Elasticsearch慢查询日志分析

Elasticsearch慢查询故障诊断

Elasticsearch一次 排查 iK 分词器 查询慢 分词多 内容大 的问题记录

Elasticsearch聚合优化 | 聚合速度提升5倍!