1、引言
Elasticsearch是非常靈活且功能豐富的搜索引擎,它提供了許多不同查詢數據的方法。在實戰業務場景中,經常會出現遠遠低於預期查詢速度的慢查詢。作爲分佈式系統的Elasticsearch,可能有各種影響查詢性能的因素,包括外部因素,如負載均衡設置,網絡延遲(帶寬,NIC卡/驅動程序)等。
本文主要討論可能導致慢查詢的原因以及如何在Elasticsearch的上下文中識別它們?
本文主要源於常見慢查詢故障的排除方法,閱讀本文的前提需要你對Elasticsearch的原理有大致的瞭解。
如果不瞭解Elastic相關原理,可以移步:elastic.blog.csdn.net 或 歷史文章。
如果不瞭解慢查詢,可以移步:爲什麼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利用率高和索引化延遲大(如下圖)。
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[ ][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[ ],"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
6、小結
本文翻譯自Elastic官方博文,添加了自己的實踐解讀和星球內部討論總結內容。
在本文中,我們討論了慢查詢的常見原因以及解決方案。我們還討論了偶發慢查詢和非偶發慢查詢的解決方案。通常會將慢查詢視爲更廣泛集羣性能出問題的典型症狀。
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
推薦閱讀:
更短時間更快習得更多幹貨!