天天看點

Elasticsearch進階調優方法論之——根治慢查詢!

Elasticsearch進階調優方法論之——根治慢查詢!
連結

如果不了解慢查詢,可以移步:為什麼Elasticsearch查詢變得這麼慢了?

本文的目的:根治慢查詢。

2、Elasticsearch慢查詢六大症狀及解決方案

在我們研究一些棘手的案例之前,讓我們從一些最常見的慢查詢及其解決方案開始。

2.1 症狀1:非活動(檢索/寫入)狀态資源使用率也非常高

症狀詳情:每個分片都消耗資源(CPU /記憶體)。即使沒有索引/搜尋請求,分片的存在也會消耗叢集開銷。

2.1.1 問題描述

叢集中的分片太多,以至于任何查詢執行起來都很慢。一個好的經驗法則——確定每個節點的非當機分片數量保持在:20以下/每GB堆記憶體。

2.1.2 解決方案

1、部署之前,設計先行。

正如VIVO搜尋技術總監振濤兄所說:“叢集規劃核心是容量預估,就好比你建個樓,必須規劃好容量,不然說用多少就建多高,吃在地基撐不住!!”。

任何部署的良好開端都是執行适當的容量規劃,以幫助确定每個搜尋用例的最佳分片數。

2、減少分片數,實施當機索引或添加其他節點以實作負載均衡。

3、考慮冷熱資料分離架構(适用于基于時間的索引)以及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主分片&1副本模型。

使用索引模闆是在建立索引階段做好設定是個好方法。(7.0及更高版本預設1主1副)。

2、 Elasticsearch 5.1或更高版本支援搜尋任務取消,這對于取消顯示在任務管理API中慢查詢任務非常有用。

任務管理:

1GET _tasks?nodes=nodeId1,nodeId2

取消任務

1POST _tasks/oTUltX4IQMOUUVeiohTt8A:12345/_cancel

3、要改進磁盤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進階調優方法論之——根治慢查詢!

Metric名額Kibana核查方法:

https://www.elastic.co/guide/en/kibana/7.0/elasticsearch-metrics.html

2.3.1 問題描述

寫入資料量大(索引化)會影響搜尋性能。

2.3.2 解決方案

1、調大重新整理頻率

将index.refresh_ interval(文檔被索引到資料搜尋可見時間間隔)增加到 30 s,通常有助于提高索引性能。

實戰中要結合具體業務場景,可能會有所不同,是以測試是關鍵。這樣避免了預設一秒生成一個分段的麻煩。

2、對于重型索引用例,請檢查我們的索引調整建議,以優化索引和搜尋性能。

包含但不限于:

1)資料初始化階段refresh設定 -1、副本設定為 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 解決方案

1、為檔案系統緩存留出至少 50 %的實體RAM。

記憶體越多,可以緩存的越多,尤其是在叢集遇到I / O問題時。假設堆大小已正确配置,剩下的任何可用于檔案系統緩存的剩餘實體RAM都可以大大加快搜尋性能。

堆記憶體大小配置建議:Min(32 GB,實體機器記憶體 / 2)。

例如,128 GB記憶體伺服器為堆提供 30GB空間,為檔案系統緩存(有時稱為OS緩存)留出剩餘記憶體,假設作業系統緩存最近通路的4KB資料塊,如果你再一次讀取相同的檔案,不需要花很長時間去磁盤上讀,直接在記憶體上讀來的更快。

2、使用query緩存和request緩存加快檢索速度。

節點級别的query緩存預設是開啟的。對應配置:

1index.queries.cache.enabled

請求緩存預設是開啟的,如果被強制關閉了,可以動态設定開啟。

1PUT /my_index/_settings

2{ "index.requests.cache.enable": true }

3、使用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 解決方案

1、要提高高基數term聚合的性能,推薦閱讀:

https://www.elastic.co/cn/blog/improving-the-performance-of-high-cardinality-terms-aggregations-in-elasticsearch

核心:使用eager_global_ordinals: true 提升性能。

2、有關進一步調整,請檢視官網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)在安全審計輸出中啟用日志或索引:

xpack.security.audit.outputs:[logfile,index]。

出于故障排除的目的,我們建議選擇logfile而不是索引,因為審計日志記錄的詳細程度可能會對叢集性能造成不必要的壓力。

審計模式可能非常冗長,是以請在完成故障排除後将其關閉。

3)在事件清單中包含authentication_success通路權限

xpack.security.audit.logfile.events.include: authentication_success

6、小結

本文翻譯自Elastic官方博文,添加了自己的實踐解讀和星球内部讨論總結内容。

在本文中,我們讨論了慢查詢的常見原因以及解決方案。我們還讨論了偶發慢查詢和非偶發慢查詢的解決方案。通常會将慢查詢視為更廣泛叢集性能出問題的典型症狀。

Elasticsearch進階調優方法論之——根治慢查詢!

8月24日北京Meetup上medcl列舉了10個原因更新7.X,如果你還是6.X、5.X甚至更低版本,推薦更新。Elasticsearch7.X進階版本在搜尋 qps 上提升很大,相同配置下慢查詢也還會有較大改善。

Elasticsearch性能優化非一朝一夕之功,“認準病根才能根除病痛”。

原文位址:

https://www.elastic.co/cn/blog/advanced-tuning-finding-and-fixing-slow-elasticsearch-queries

官方優化:

https://www.elastic.co/guide/en/elasticsearch/reference/7.0/how-to.html

推薦閱讀:

Elasticsearch性能優化實戰指南

讓Elasticsearch飛起來!——性能優化實踐幹貨