Elasticsearch高级调优方法论之——根治慢查询!

一、引言
Elasticsearch是很是灵活且功能丰富的搜索引擎,它提供了许多不一样查询数据的方法。在实战业务场景中,常常会出现远远低于预期查询速度的慢查询。做为分布式系统的Elasticsearch,可能有各类影响查询性能的因素,包括外部因素,如负载均衡设置,网络延迟(带宽,NIC卡/驱动程序)等。
本文主要讨论可能致使慢查询的缘由以及如何在Elasticsearch的上下文中识别它们?
本文主要源于常见慢查询故障的排除方法,阅读本文的前提须要你对Elasticsearch的原理有大体的了解。
若是不了解Elastic相关原理,能够移步:elastic.blog.csdn.net 或 历史文章。
若是不了解慢查询,能够移步:为何Elasticsearch查询变得这么慢了?
本文的目的:根治慢查询。
二、Elasticsearch慢查询六大症状及解决方案
在咱们研究一些棘手的案例以前,让咱们从一些最多见的慢查询及其解决方案开始。
2.1 症状1:非活动(检索/写入)状态资源利用率也很是高
症状详情:每一个分片都消耗资源(CPU /内存)。即便没有索引/搜索请求,分片的存在也会消耗集群开销。
2.1.1 问题描述
集群中的分片太多,以致于任何查询执行起来都很慢。一个好的经验法则——确保每一个节点的非冻结分片数量保持在:20如下/每GB堆内存。
2.1.2 解决方案
一、部署以前,设计先行。
正如VIVO搜索技术总监振涛兄所说:“集群规划核心是容量预估,就比如你建个楼,必须规划好容量,否则说用多少就建多高,吃在地基撑不住!!”。
任何部署的良好开端都是执行适当的容量规划,以帮助肯定每一个搜索用例的最佳分片数。
二、减小分片数,实施冻结索引或添加其余节点以实现负载均衡。
三、考虑冷热数据分离架构(适用于基于时间的索引)以及Elasticsearch中的翻转索引(rollover)/压缩索引(shrink)功能,以有效管理分片计数。
推荐阅读:我在 Elasticsearch 集群内应该设置多少个分片?
https://www.elastic.co/cn/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster
Elasticsearch5.x冷热架构实现
https://www.elastic.co/cn/blog/hot-warm-architecture-in-elasticsearch-5-x
容量规划最佳实践(必读)
https://www.elastic.co/guide/en/elasticsearch/guide/master/capacity-planning.html
2.2 症状2:线程池存在大量rejected
搜索线程池显示“拒绝”计数的持续增长,该计数基于上次群集从新启动而累积。
1GET / _cat / thread_pool / search?v&h = node_name,name,active,rejected,completed
响应以下:
1node_name name active rejected completed
2instance-0000000001 search 0 10 0
3instance-0000000002 search 0 20 0
4instance-0000000003 search 0 30 0
2.2.1 问题描述
场景1:查询的目标是太多分片,超过集群中的CPU核数。这会在搜索线程池中建立排队任务,从而致使搜索拒绝。
场景2:磁盘I/O速度慢或在某些状况下彻底饱和的CPU致使搜索排队。
2.2.2 解决方案
一、建立索引时采用1主分片&1副本模型。
使用索引模板是在建立索引阶段作好设置是个好方法。(7.0及更高版本默认1主1副)。
二、 Elasticsearch 5.1或更高版本支持搜索任务取消,这对于取消显示在任务管理API中慢查询任务很是有用。
任务管理:
1GET _tasks?nodes=nodeId1,nodeId2
取消任务
1POST _tasks/oTUltX4IQMOUUVeiohTt8A:12345/_cancel
三、要改进磁盘I / O,请查看咱们的存储建议,并确保使用推荐的硬件以得到最佳性能。
存储优化建议:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tune-for-indexing-speed.html#_use_faster_hardware
2.3 症状3:高CPU和索引化延迟
当集群不堪重负时,度量标准关联显示CPU利用率高和索引化延迟大(以下图)。
Elasticsearch高级调优方法论之——根治慢查询!html

Metric指标Kibana核查方法:
https://www.elastic.co/guide/en/kibana/7.0/elasticsearch-metrics.html
2.3.1 问题描述
写入数据量大(索引化)会影响搜索性能。
2.3.2 解决方案
一、调大刷新频率
将index.refresh_ interval(文档被索引到数据搜索可见时间间隔)增长到 30 s,一般有助于提升索引性能。
实战中要结合具体业务场景,可能会有所不一样,所以测试是关键。这样避免了缺省一秒生成一个分段的麻烦。
二、对于重型索引用例,请检查咱们的索引调整建议,以优化索引和搜索性能。
包含但不限于:
1)数据初始化阶段refresh设置 -一、副本设置为 0,以提高写入速度;写入完毕后复原。
2)关闭swapping。
3)使用文件系统缓存。
4)使用自动生成ID。
性能调优实践:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tune-for-indexing-speed.html#_disable_refresh_and_replicas_for_initial_loads
2.4 症状4:副本增长后延时增大
在增长副本分片计数(例如,从1到2)以后能够观察到查询等待时间。若是存在更多数据,则缓存的数据将很快被逐出,致使操做系统层面页面错误增长。
2.4.1 问题描述
文件系统缓存没有足够的内存来缓存常常查询的索引部分。
Elasticsearch的查询缓存实现了LRU置换算法:当缓存变满时,最近最少使用的数据被置换以便为新数据腾出空间。
请求缓存:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-cache.html
2.4.2 解决方案
一、为文件系统缓存留出至少 50 %的物理RAM。
内存越多,能够缓存的越多,尤为是在集群遇到I / O问题时。假设堆大小已正确配置,剩下的任何可用于文件系统缓存的剩余物理RAM均可以大大加快搜索性能。
堆内存大小配置建议:Min(32 GB,物理机器内存 / 2)。
例如,128 GB内存服务器为堆提供 30GB空间,为文件系统缓存(有时称为OS缓存)留出剩余内存,假设操做系统缓存最近访问的4KB数据块,若是你再一次读取相同的文件,不须要花很长时间去磁盘上读,直接在内存上读来的更快。
二、使用query缓存和request缓存加快检索速度。
节点级别的query缓存默认是开启的。对应配置:
1index.queries.cache.enabled
请求缓存默认是开启的,若是被强制关闭了,能够动态设置开启。
1PUT /my_index/_settings
2{ "index.requests.cache.enable": true }
三、使用preference优化高速缓存
可使用搜索请求首选项preference来优化全部这些高速缓存。以便每次将某些搜索请求路由到同一组分片,而不是在可用的不一样副本之间交替。
这将更好地利用请求缓存、节点查询缓存和文件系统缓存。
2.5 症状5:共享硬件资源时的高资源利用率。
操做系统显示始终较高的CPU 、磁盘、I / O使用率。
中止第三方应用程序后能够看到性能提高。
2.5.1 问题描述
其余进程(例如Logstash)和Elasticsearch自己之间存在资源(CPU、内存、或磁盘I / O)争用。
2.5.2 解决方案
给Elasticsearch隔离的硬件环境或虚拟环境。
避免在共享硬件上与其余资源密集型应用程序一块儿运行Elasticsearch。
2.6 症状6:聚合N多惟一值引发的高内存使用率
查询包含惟一值(例如,ID,用户名,电子邮件地址等)的聚合字段时性能不佳。
在堆内存分析时发现:Java对象使用"search", "buckets", "aggregation"等术语,消耗大量的堆内存。
2.6.1 问题缘由
聚合在高基数(high-cardinality)字段上运行,须要大量资源来获取许多存储桶。
还能够存在涉及nested字段和/或join字段的嵌套聚合。
注解:high-cardinality中文解读为高基数很差理解。举个例子:
高基数——列中有不少惟一值(),如主键
低基数——与之相反,如性别列(只有男、女)。
2.6.2 解决方案
一、要提升高基数term聚合的性能,推荐阅读:
https://www.elastic.co/cn/blog/improving-the-performance-of-high-cardinality-terms-aggregations-in-elasticsearch
核心:使用eager_global_ordinals: true 提高性能。
二、有关进一步调整,请查看官网nested字段类型和join字段类型的使用建议,以更好地提升聚合性能。
3 偶发慢查询解决方案
通常而言,偶尔或间歇性慢查询能够从官网的优化索引、优化检索建议中中受益。
3.1 偶发慢查询关联监控指标
偶发慢查询应与这些监控指标中的一个或多个密切相关:
1)CPU负载
2)索引吞吐量
3)搜索吞吐量
4)垃圾收集(GC)活动
5)搜索线程池队列大小
线程池查看方法:
1GET /_cat/thread_pool
3.2 ARS提高检索吞吐率
Elasticsearch还有另外一个有用的功能,称为自适应副本选择(ARS),它容许协调节点了解数据节点上的负载,并容许它选择最佳的分片副原本执行搜索,从而提升搜索吞吐量、下降延迟。
经过在查询时间内更均匀地分散负载,ARS能够对偶尔的减速有很大帮助。
在Elasticsearch 7.0及更高版本中,默认状况下将启用ARS。
4 非偶发慢查询解决方案
对于非偶发慢查询的场景,咱们能够尝试逐个删除查询中的功能,并检查查询是否仍然很慢。
4.1 “拆解DSL”排查慢查询根源
查找最简单查询以重现性能问题有助于隔离和识别问题:
1)没有高亮显示它仍然很慢吗?
2)没有聚合,它仍然很慢吗?
3)若是size设置为0,它仍然很慢吗?
当size设置为0时,Elasticsearch会缓存搜索请求的结果,以便更快地进行搜索
4.2 参考官方搜索优化建议,看是否凑效?
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tune-for-search-speed.html
4.3 慢查询排除实践
1)启用"profile:true"。
1GET /twitter/_search
2{
3 "profile": true,
4 "query" : {
5 "match" : { "message" : "some number" }
6 }
7}
2)查看节点的热点线程。
这有助于了解CPU时间的使用状况。
1GET /_nodes/hot_threads
3)使用kibana可视化profile分析工具
https://www.elastic.co/guide/en/kibana/7.0/xpack-profiler.html
5 捕获慢查询、耗费资源查询
5.1 慢查询、耗费资源查询难捕获
在Elasticsearch中同时处理不一样的请求/线程时,很难捕获慢查询、耗费资源查询。
实际N多人应用的业务场景,当没法定位耗费资源查询的用户时,状况变得更加复杂,这些查询会下降集群性能(例如,长垃圾收集(GC)周期)或更糟糕的是内存不足(OOM)状况。
在Elasticsearch 7.0版中,咱们引入了一种新的内存熔断策略,用于在保留内存时测量实际堆内存使用状况。
此新策略可提升节点对资源耗费高查询致使集群过载的弹性支持,并在默认状况下处于打开状态,并可以使用新的集群设置:
indices.breaker.total.use_real_memory 进行控制。
内存熔断策略推荐:
https://github.com/elastic/elasticsearch/pull/31767
5.2 dump堆内存分析
以上方案并未覆盖所有业务场景。借助dump文件有助于更好地理解根本缘由。
在JVM OOM后Dump操做实战参考:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/heap-dump-path.html
Linux捕获dump文件的方法
1ps -ef|egrep 'elasticsearch|logstash' | grep -v grep
5.3 Elasticsearch的保护设置
Elasticsearch具备另外一个保护设置(最大桶search.max_buckets限制),以保护集群出现OOM。
当超过桶的数量(在版本7.0中默认为10,000)时(例如,当运行多层聚合时),
该最大桶聚合设置中止执行而且使搜索请求失败。
5.4 断路器设置
为了进一步识别潜在的耗费资源的查询,咱们能够设置断路器(indices.breaker.request.limit)。
设置方法:逐步缩放查询范围,从低阈值开始隔离查询并逐渐向上移动阈值以缩小到特定的查询。
断路器设置参考:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/circuit-breaker.html#request-circuit-breaker
5.5 慢日志分析
能够经过启用Elasticsearch中的慢速日志来识别运行缓慢的查询。
Slowlogs专门用于分片级别,这意味着只应用数据节点。
仅协调 Coordinating-only/客户client节点不具有慢日志分析功能,由于它们不保存数据(索引/分片)。
Slowlogs有助于回答如下问题:
1)查询须要多长时间?
2)查询请求正文的内容是什么?
Slowlogs输出举例:
1[2019-02-11T16:47:39,882][TRACE][index.search.slowlog.query] [2g1yKIZ] [logstash-20190211][4] took[10.4s], took_millis[10459], total_hits[16160], types[], stats[],
2search_type[QUERY_THEN_FETCH], total_shards[10], source[{"size":0,"query":{"bool":{"must":[{"range":{"timestamp":{"from":1549266459837,"to":1549871259837,"include_lower":true,
3"include_upper":true,"format":"epoch_millis","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"_source":{"includes":[],"excludes":[]},"stored_fields":"*","docvalue_fields":
4[{"field":"timestamp","format":"date_time"},{"field":"utc_time","format":"date_time"}],"script_fields":{"hour_of_day":{"script":{"source":"doc['timestamp'].value.getHourOfDay()",
5"lang":"painless"},"ignore_failure":false}},"aggregations":{"maxAgg":{"max":{"field":"bytes"}},"minAgg":{"min":{"field":"bytes"}}}}], id[]],
Slowlog 日志拆解:
日志拆分项
描述
[2019-02-11T16:47:39,882]
检索时间
[TRACE]
日志级别
[index.search.slowlog.query]
属于search的query阶段慢日志
[2g1yKIZ]
节点名称
[logstash-20190211]
索引名称
[4]
query执行的分片序号
took[10.4s]
在分片4所需的处理时间。注意:在查看慢速日志时,咱们但愿避免从不一样的分片中添加全部时间,由于每一个分片可能并行执行。
took_millis[10459]
耗费时间(毫秒)
total_hits[16160]
命中数
search_type[QUERY_THEN_FETCH]
search类型(query_then_fetch)
total_shards[10]
索引的总分片大小
source[]
执行检索的请求body体
5.6 日志审计(高阶功能,低版本非付费会员建议跳过)
拥有金牌会员或铂金会员订阅的客户(包括Elastic安全功能)能够打开审核日志以捕获有关查询的更多详细信息。(用户能够开始为期30天的试用版来测试Elastic安全功能。)
注意:6.8和7.1以后,基础安全功能已免费。之上的高版本可使用该功能。低版本的非会员不建议使用。
审计日志记录有助于回答如下问题:
1)查询是何时发生的?
2)谁执行了查询?
3)查询的内容是什么?
咱们须要调整审核设置,由于默认设置至关繁琐:
1)启用安全审计日志:
在elasticsearch.yml中设置
xpack.security.audit.enabled:true。
2)在安全审计输出中启用日志或索引:
在elasticsearch.yml中设置
xpack.security.audit.outputs:[logfile,index]。
出于故障排除的目的,咱们建议选择logfile而不是索引,由于审计日志记录的详细程度可能会对集群性能形成没必要要的压力。
审计模式可能很是冗长,所以请在完成故障排除后将其关闭。
3)在事件列表中包含authentication_success访问权限
在elasticsearch.yml中设置
xpack.security.audit.logfile.events.include: authentication_success
六、小结
本文翻译自Elastic官方博文,添加了本身的实践解读和星球内部讨论总结内容。
在本文中,咱们讨论了慢查询的常见缘由以及解决方案。咱们还讨论了偶发慢查询和非偶发慢查询的解决方案。一般会将慢查询视为更普遍集群性能出问题的典型症状。
Elasticsearch高级调优方法论之——根治慢查询!node

8月24日北京Meetup上medcl列举了10个缘由升级7.X,若是你仍是6.X、5.X甚至更低版本,推荐升级。Elasticsearch7.X高级版本在搜索 qps 上提高很大,相同配置下慢查询也还会有较大改善。
Elasticsearch性能优化非一朝一夕之功,“认准病根才能根除病痛”。git

相关文章
相关标签/搜索