0x00 概述
ES集群又慢查詢記錄到log的功能,有時候研發反應es查詢比較慢,此時在確認集群健康,green,indices數據green,集群負載正常后,可以打開該功能排查es查詢慢的問題。
elasticsearch提供了非常靈活的搜索條件給我們使用,在使用復雜表達式的同時,如果使用不當,可能也會為我們帶來了潛在的風險,因為影響查詢性能的因素很多很多,這篇筆記主要記錄一下慢查詢可能的原因,及其優化的方向。
本文討論的es版本為7.0+。
0x01 慢查詢現象
1.1 查詢服務超時
-
最直觀的現象就是提供查詢的服務響應超時。
大量連接被拒絕
我們有時候寫查詢,為了圖方遍,經常使用通配符*來查詢,這有可能會匹配到多個索引,由於索引下分片太多,超過了集群中的核心數。就會在搜索線程池中造成排隊任務,從而導致搜索拒絕。
1.2 查詢延遲
主機CPU飆高
- 另一個常見原因是磁盤 I/O 速度慢,導致搜索排隊或在某些情況下 CPU 完全飽和。
- 除了文件系統緩存,Elasticsearch 還使用查詢緩存和請求緩存來提高搜索速度。 所有這些緩存都可以使用搜索請求進行優化,以便每次都將某些搜索請求路由到同一組分片,而不是在不同的可用副本之間進行交替。這將更好地利用請求緩存、節點查詢緩存和文件系統緩存。Es默認會在內存使用75%時發生FullGC ,做好主機和節點的監控同樣重要。
0x02 優化方法
2.1 根據查詢時間段動態計算索引
- elasticsearch支持同時查詢多個索引,為了提高查詢效率,避免使用通配符查詢,我們可以計算枚舉出所有的目標索引,一般es的數據都是按時間分索引,我們可以根據前端傳入的時間段,計算出目標索引。
2.2 控制分片數量
- 分片的數量和節點和內存有一定的關系。
- 最理想的分片數量應該依賴於節點的數量。 數量是節點數量的1.5到3倍。
- 每個節點上可以存儲的分片數量,和堆內存成正比。官方推薦:1GB 的內存,分片配置最好不要超過20。
注意from/to查詢帶來的深度分頁問題
- 舉例假如每頁為 10 條數據,你現在要查詢第 200 頁,實際上是會把每個 Shard 上存儲的前 2000條數據都查到一個協調節點上。
如果你有 5 個 分片,那么就有 10000 條數據,接着協調節點對這 10000 條數據進行一些合並、處理,再獲取到最終第 200 頁的 10 條數據。實在需要查詢很多數據,可以使用scroll API 滾動查詢。
2.3 為你的索引配置索引模板
- 在低版本的es中默認的分片是5個,在高版本中改成了1,我們需要根據索引的索引量來動態調整分片數量,這里推薦設置一個默認匹配規則,將優先級設置高一些(ps:order高的會覆蓋order低的模板),避免查詢掃描過多的分片,合理利用集群資源。
2.4 避免數據分桶太多
對於分桶數量太大的聚合請求,應該將所有數據切片,比如按時間分片,多次請求,來提高查詢效率,並且避免內存OOM。
2.5 獨立協調節點
- 集群中應該有獨立的協調節點,專門用於數據請求(node.master=false node.data=false),並給它們設置足夠的內存。通過數據節點與協調節點分離,可以避免節點掛掉之后,導致整個集群不可用,或者長時間響應遲鈍。
2.6 適當的增加刷新間隔
- es是一個准實時的搜索框架,這就意味着,從索引一個文檔直到文檔能夠被搜索到有一個輕微的延遲,也就是 index.refresh_ interval ,默認值是1秒,適當的增加這個值,可以避免創建過多的segment(segment是最小的檢索單元)。
2.7 配置慢查詢日志
- 通過在 Elasticsearch 中啟用 slowlogs 來識別運行緩慢的查詢。slowlogs 專門用於分片級別,僅適用於數據節點。協調/客戶端節點不具備慢日志分析功能,因為它們不保存數據。通過它,我們可以在日志中看到,那個查詢語句耗時長,從而制定優化措施。
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.query.debug: 2s
index.search.slowlog.threshold.query.trace: 500ms
index.search.slowlog.threshold.fetch.warn: 1s
index.search.slowlog.threshold.fetch.info: 800ms
index.search.slowlog.threshold.fetch.debug: 500ms
index.search.slowlog.threshold.fetch.trace: 200ms
index.search.slowlog.level: info
2.8 配置熔斷策略
- es7.0后版本提供一系列的斷路器,用於防止操作引起OutOfMemoryError。每個斷路器都指定了可以使用多少內存的限制。此外,還有一個父級斷路器,用於指定可在所有斷路器上使用的內存總量。
indices.breaker.request.limit:請求中斷的限制,默認為JVM堆的60%。 indices.breaker.total.limit:總體父中斷程序的啟動限制,如果indices.breaker.total.use_real_memory為,則默認為JVM堆的70% false。如果indices.breaker.total.use_real_memory 為true,則默認為JVM堆的95%。 network.breaker.inflight requests.limit 限制當前通過HTTP等進來的請求使用內存不能超過Node內存的指定值。這個內存主要是限制請求內容的長度。 默認100%。 script.max_compilations_rate:在允許的時間間隔內限制動態腳本的並發執行數量。默認值為75 / 5m,即每5分鍾75。
0x03 配置慢查詢日志
3.1 通過修改elasticsearch.yml來啟用慢查詢(需要重啟集群,不推薦)
vim elasticsearch.yml
Search Slow Log配置
###Search Slow Log :查詢慢日志配置,日志記錄在以“_index_isearch_slowlog.log” 結尾的文件中 #注:配置不一定都需要,自己選擇需要那種級別(warn、info、debug、trace)日志,關閉的話配置成-1 就可以了,注釋掉重啟也可以 index.search.slowlog.threshold.query.warn: 10s #超過10秒的query產生1個warn日志 index.search.slowlog.threshold.query.info: 5s #超過5秒的query產生1個info日志 index.search.slowlog.threshold.query.debug: 2s #超過2秒的query產生1個debug日志 index.search.slowlog.threshold.query.trace: 500ms #超過500毫秒的query產生1個trace日志 index.search.slowlog.threshold.fetch.warn: 1s ##fetch階段的配置 index.search.slowlog.threshold.fetch.info: 800ms index.search.slowlog.threshold.fetch.debug: 500ms index.search.slowlog.threshold.fetch.trace: 200ms
Index Slow log配置
###Index Slow log:索引慢日志配置 ,日志記錄在以“_index_indexing_slowlog.log” 結尾的文件中 #注:上邊四個配置不一定都需要,自己選擇需要那種級別(warn、info、debug、trace)日志關閉的話配置成-1就可以了 index.indexing.slowlog.threshold.index.warn: 10s ##索引數據超過10秒產生一個warn日志 index.indexing.slowlog.threshold.index.info: 5s ##索引數據超過5秒產生一個info日志 index.indexing.slowlog.threshold.index.debug: 2s ##索引數據超過2秒產生一個ddebug日志 index.indexing.slowlog.threshold.index.trace: 500ms ##索引數據超過500毫秒產生一個trace日志
3.2 通過API動態的修改配置
https://www.elastic.co/guide/en/elasticsearch/reference/7.x/index-modules-slowlog.html 官網參考
這是一個索引級別的設置,也就是說可以獨立應用給單個索引:這個配置是永久的,配置后即使集群重啟也會保留。如果關閉日志記錄的話將選項修改成-1即可(例如: "index.search.slowlog.threshold.query.warn" : -1)
Search Slow Log配置
curl -user 用戶名:密碼 -X PUT "192.168.1.3:9200/索引名字/_settings?pretty" -H 'Content-Type: application/json' -d' { "index.search.slowlog.threshold.query.warn": "10s", "index.search.slowlog.threshold.query.info": "5s", "index.search.slowlog.threshold.query.debug": "2s", "index.search.slowlog.threshold.query.trace": "500ms", "index.search.slowlog.threshold.fetch.warn": "1s", "index.search.slowlog.threshold.fetch.info": "800ms", "index.search.slowlog.threshold.fetch.debug": "500ms", "index.search.slowlog.threshold.fetch.trace": "200ms", "index.search.slowlog.level": "info" } '
Index Slow log配置
curl -user 用戶名:密碼 -X PUT "192.168.1.3:9200/索引名字/_settings?pretty" -H 'Content-Type: application/json' -d' { "index.indexing.slowlog.threshold.index.warn": "10s", "index.indexing.slowlog.threshold.index.info": "5s", "index.indexing.slowlog.threshold.index.debug": "2s", "index.indexing.slowlog.threshold.index.trace": "500ms", "index.indexing.slowlog.level": "info", "index.indexing.slowlog.source": "1000" } '
0x04 參考
https://www.cnblogs.com/hyq0823/p/12165113.html
https://blog.csdn.net/donghaixiaolongwang/article/details/79208457