1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      如何解析Elasticsearch的查詢毛刺現(xiàn)象,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

      10年積累的成都做網(wǎng)站、成都網(wǎng)站建設(shè)經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有大名免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

      如果業(yè)務(wù)對查詢延遲很敏感,Elasticsearch 查詢延遲中的毛刺現(xiàn)象就是比較困擾的一類問題,由于出現(xiàn)毛刺的時間點已經(jīng)過去,無法穩(wěn)定復(fù)現(xiàn),對于根因的分析比較困難,無法用系統(tǒng)化調(diào)試的思想,從現(xiàn)象出發(fā)逐步推理,定位問題,能做的通常就是看一下監(jiān)控系統(tǒng)對應(yīng)時間點的指標(biāo)情況,而在 es 中,導(dǎo)致查詢延遲發(fā)生波動的因素非常多,今天我們來列舉一下可能的因素,并嘗試用對應(yīng)的方法來定位和解決他們。

      通常一個系統(tǒng)中會有多種不同的查詢同時存在,他們本身正常的查詢延遲就可能存較大差異,因此即使系統(tǒng)在理想狀態(tài)下,查詢延遲的曲線也可能存在較大波動,特別是查詢條件不固定,某些查詢本身就耗時較長。我們只討論一個特定的查詢語句在某個時刻產(chǎn)生了較大延遲,即這個查詢語句正常不應(yīng)該耗時那么久。

      另外 es 和 lucene 層面的查詢緩存只是一種優(yōu)化,查詢緩存本身并不能保證查詢延遲。

      GC 的影響

      查詢延遲受 GC 的影響是常見因素之一,一個查詢被轉(zhuǎn)發(fā)的相關(guān)分片,任意節(jié)點產(chǎn)生一個長時間的 GC 都會導(dǎo)致整個查詢耗時變長。

      定位方式:
      查看對應(yīng)時間點的節(jié)點 GC 指標(biāo),參考 kibana 或 gc log

      解決方式:
      堆內(nèi)存不足可能的因素比較多,例如配置的 JVM內(nèi)存較小,open 的索引過多,導(dǎo)致 FST 占用空間過大(未開啟 offheap 的情況下),聚合占用了大量內(nèi)存,netty 層占用大量內(nèi)存,以及 cache 占用的內(nèi)存等,主要是根據(jù)自己的業(yè)務(wù)特點,找到內(nèi)存被誰占用了,然后合理規(guī)劃JVM 內(nèi)存空間。可以通過 REST API 或 MAT 分析內(nèi)存,參考命令:

      curl -sXGET "http://localhost:9200/_cat/nodes?h=name,port,segments.memory,segments.index_writer_memory,segments.version_map_memory,segments.fixed_bitset_memory,fielddata.memory_size,query_cache.memory_size,request_cache.memory_size&v"

      HBase 通過 offheap 的方式降低 JVM 占用,來避免 FGC,es 將 FST offheap 后也大幅降低了 JVM 占用情況,不過 FST offheap 之后有可能會被系統(tǒng)清理,再次查詢 FST 就會發(fā)生 io,也會造成查詢延遲不穩(wěn)定,不過這種概率非常小。而在 es 中聚合,scroll等操作都可能導(dǎo)致 JVM 被大幅占用,增加了不確定性。

      系統(tǒng) cache 失效

      查詢,以及聚合,需要訪問磁盤上不同的文件,es 建議為系統(tǒng) cache 保留一半的物理內(nèi)存空間,當(dāng)系統(tǒng) cache 失效,發(fā)生磁盤 io,對查詢延遲產(chǎn)生明顯的影響。pagecache 什么時候會失效?使用 pagecache 的地方很多,linux 默認會緩存絕大部分的文件讀寫,例如查詢,寫日志,入庫寫 segment 文件,merge 時讀寫的文件,以及es 所在節(jié)點部署的其他的程序、腳本文件執(zhí)行的對 io 上面的操作等都會搶占 pagecache。linux 按一定策略和閾值來清理 pagecache,應(yīng)用層無法控制哪些文件不被清理。

      因此我們需要了解一個查詢語句在 io 上的需求,主要是以下兩個問題:

      • 查詢過程需要實時讀取哪些文件?

      • 一次查詢需要幾次 io?讀取多少字節(jié)?消耗多少時間?

      查詢過程需要實時讀取哪些文件

      es 中的查詢是一個復(fù)雜的過程,不同的查詢類型需要訪問不同的 lucene 文件,我將常見類型的查詢可能訪問的文件整理如下:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      真正查詢過程中,并非所有文件都會實時讀取,有些文件已經(jīng)在 open 索引的時候讀取完畢常駐內(nèi)存,有些元信息文件也是在 open 的時候解析一次。為了驗證搜索過程實際訪問的文件與預(yù)期是否一致,我寫了一個 systemtap 腳本來 hook 系統(tǒng)調(diào)用的 read 及 pread 函數(shù),并把調(diào)用情況打印出來,驗證過程樣本數(shù)據(jù)使用 geonames 索引,為了便于演示,將索引 forcemerge 為單個分段,并將 store 設(shè)置為 niofs。

      僅查詢,不取回
      分布式搜索由兩階段組成,當(dāng)請求中 size=0時,只執(zhí)行查詢階段,不需要取回。因此 term 查詢或 match 查詢,因此查詢過程一般只需要用到倒排索引,因此,如下類型的查詢:

      _search?size=0
      {
       "query": {
         "match": {
           "name": {
             "query": "Farasi"
           }
         }
       }
      }

      只需要讀取 tim 文件。因為tip 是在內(nèi)存常駐的,而 size=0的時候只需要返回 hit 數(shù)量,es 在實現(xiàn)的時候有一個提前終止的優(yōu)化,直接從 tim 中取 docFreq 作為 hit,不需要訪問 postings list。

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      但是當(dāng)查詢含有 post_filter ,自定義的terminate_after等情況時,不會走提前終止的優(yōu)化過程。再者就是類似如下的多個查詢條件時,lucene 需要對每個字段的查詢結(jié)果做交并集,這就需要拿到 postings list才行:

      _search?size=0
      {
       "query": {
         "bool": {
           "must":     { "match": { "name": "Farasi" }},
           "must_not": { "match": { "feature_code": "CMP"  }}
         }
       }
      }

      因此會讀取 .doc 文件:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      當(dāng) size!=0 時,term 查詢和 match 查詢需要讀取的文件不一樣,因此下面單獨討論。

      term查詢,加取回
      帶上 fetch 階段后,原來查詢過程需要訪問的文件不變,fetch 過程需要從 stored fields 中取,因為 _source 字段本身就是存儲到 stored fields 中的。

      _search?size=1
      {
       "query": {
         "term": {
           "country_code.raw": {
             "value": "CO"
           }
         }
       }
      }

      因此,需要相比僅查詢的過程,還需要多訪問 fdt,fdx文件。

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      match查詢,加取回

      match 查詢由于需要計算評分,需要使用 Norms 信息,因此在 term 查詢加取回的基礎(chǔ)上還要多訪問 Norms 文件

      _search?size=10
      {
       "query": {
         "match": {
           "name": {
             "query": "Farasi"
           }
         }
       }
      }

      需要讀取 Norms中的 nvd 文件:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      數(shù)值類型查詢
      數(shù)值類型的字段使用 BKD-tree 建立索引,不會存儲到倒排,因此查詢過程需要讀取 Point Value。取回過程與 term 查詢相同。

      _search?size=0
      {
       "query": {
         "range": {
           "geonameid": {
             "gte": 3682501,
             "lte": 3682504
           }
         }
       }
      }

      查詢過程只需要讀取 dim 文件:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      聚合

      對于 metric 和 bucket 聚合,需要訪問的文件相同,當(dāng) size=0時,只需要讀取 dvd 文件。

      _search?size=0
      {
       "aggs": {
         "name": {
           "terms": { "field": "name.raw" }
         }
       }
      }

      以下為部分截圖,省略了后面的3萬多條記錄。

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      GET API

      使用 GET API獲取單條文檔時,與 fetch 過程并不相同

      _doc/IrOMznAB5onF36XmwY4W

      以下結(jié)果想必會出乎意料:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      ?_id 字段是被建立了索引的。這個 _id 是 es 層面概念,并非 lucene 倒排表里的 docid,因此根據(jù) _id 單條 GET 的時候,需要先執(zhí)行一次 lucene 查詢(termsEnum.seekExact)來獲取 lucene 中數(shù)字類型的 docid,查詢過程自然需要查找 FST,讀取 tim。

      然后根據(jù)這個 docid 去 stored field 中讀取 _source,因此需要讀取 fdx,fdt 文件

      最后,GET API 除了返回 _source 之外,還要返回該文檔的元信息字段,包括:_version、_seq_no、_primary_term,這三個字段是保存在 docvalue 中的,因此需要讀取 dvd 文件。

      兩階段的查詢過程中,query 階段返回的 docid 是 lucene 內(nèi)部數(shù)字類型的 id,fetch 的時候可以直接獲取了。

      查詢需要幾次 io?

      在了解了查詢會涉及到動態(tài)讀取哪些文件之后,我們還需要知道在 io 上需要多大的代價,為了驗證實際搜索過程的 io 情況,我們再編寫一個新的 systemtap 腳本,將查詢過程對每個文件讀取的字節(jié)數(shù),耗費時間等信息打印出來:

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      為了觀測到查詢在 io 上的影響,我們需要排除一些干擾因素:

      無 pagecache 的測試:

      • 用 vmtouch 驅(qū)逐該索引在 pagecache 的緩存

      • 執(zhí)行 _cache/clear 清理 es 層面的緩存

      有 pagecache 的測試:

      • 執(zhí)行 _cache/clear 清理 es 層面的緩存

      • 使用相同查詢執(zhí)行第2次

      此外,系統(tǒng)環(huán)境干凈,單節(jié)點,沒有寫入操作,沒有其他無關(guān)進程影響。然后對幾種常見類型的查詢進行統(tǒng)計,結(jié)果如下表:?

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      你可能不想看這種明細表,我來總結(jié)一下:多數(shù)查詢所需的 read 調(diào)用次數(shù)及需要讀取的數(shù)據(jù)量都不大,但是有兩種情況需要較多的 io,因為他們都與數(shù)據(jù)量有關(guān):

      • 聚合的時候,所需 io 取決于參與聚合的數(shù)據(jù)量。

      • 數(shù)值類型的 range query,所需 io 取決于命中的結(jié)果集大小。

      業(yè)務(wù)對于上述兩種類型的查詢要特別關(guān)注。可以考慮設(shè)法優(yōu)化,例如聚合前盡量通過查詢條件縮小參與聚合的結(jié)果集,以及 range 查詢的時候盡量縮小范圍。其次還有兩種情況需要的 io 相對較多,但比上面的要少一個數(shù)量級:

      • 多條件查詢時,需要對多個字段的結(jié)果集做交并,結(jié)果集較大時,需要讀取doc 文件的次數(shù)較多,本例中有幾十次。

      • 深度翻頁,要取決于要取回的數(shù)據(jù)量。因為單條 GET 那讀那么多的文件,代價略大。

      結(jié)論:在僅查詢的場景下,訪問 doc 和 dim 文件的次數(shù)可能會比較多,通常業(yè)務(wù)的查詢語句都比較復(fù)雜,混合多種查詢條件,io 量雖然是很大,但是當(dāng)磁盤比較繁忙,而 page cache又未命中的情況下,查詢延遲可能會比較大。 

      FST offheap 后的影響

      FST 的 offheap 通過 mmap tip 文件,讓 FST 占用的內(nèi)存空間從堆內(nèi)轉(zhuǎn)向 pagecache 來實現(xiàn),既然在 pagecache 中,當(dāng)被 pagecache 驅(qū)逐后,就會產(chǎn)生 io,產(chǎn)生明顯的查詢延遲。簡單來說就是這種 offheap 的效果有可能導(dǎo)致 FST 不在 heap 了。

      雖然 tip 被逐出 pagecache 的幾率很小,但是,隨著集群規(guī)模變大,偶然因素就會變成必現(xiàn)情況。

      解決方式:自研一種 offheap也很簡單, FST 的查找過程就是在數(shù)組里跳來跳去的找,所以比 HBase 的 offheap 簡單很多。如果不想改代碼,解決方式參考上一條。

      如何觀測查詢在 io 上的延遲

      當(dāng)生產(chǎn)環(huán)境查詢延遲產(chǎn)生毛刺,我們想要確定這個較高的延遲是否受 io 的影響導(dǎo)致,但是很不幸,目前還很難觀測到,即使查詢延遲毛刺發(fā)生在當(dāng)下,Profile API 也無法給出在 io 上的耗時(通過 systemtap 腳本中為 pread 過程注入延遲,發(fā)現(xiàn)讀取 tim 文件的耗時在 Profile結(jié)果里體現(xiàn)不出來的,fdt,fdx文件的讀取延遲體現(xiàn)在create_weight字段,dim 文件的讀取延遲體現(xiàn)在build_scorer字段等,難以界定問題)發(fā)現(xiàn)如果想要觀測到這些指標(biāo),需要在 lucene 層面做出一些改進,然后在 Profile API 和 Slow log 中展示出來,而且還僅限于使用 niofs 的情況下才能拿到指標(biāo)。

      既然搜索需要不可控次數(shù)的 io,搜索延遲就注定是無法保障的。例如:

      • 索引寫入會占用io,雖然不多,但是存在瞬間刷盤的時刻

      • 如果有 update,會比 index 操作占用更多 io util

      • 如果存在巨大的 shard,查詢可能會占用較大 io util

      • 單個節(jié)點的多個磁盤之間可能是負載不均的。

      • merge,recovery,甚至更新集群狀態(tài),都需要 io

      磁盤 io 導(dǎo)致的問題,就用 ssd或內(nèi)存來解決,HDFS 里將存儲類型分為 RAM,SSD,DISK 等幾種類型,再根據(jù)不同的存儲策略控制副本在不同存儲介質(zhì)的分布,在 es 里也是類似的機制:

      • 第一種是索引級別的冷熱分離,用 node.attr 配合索引級別的 allocation策略來實現(xiàn),讓熱索引存儲到 ssd,索引的寫入和查詢過程都不變。

      • 第二種可以考慮讓主分片放到 RAM,例如 /dev/shm,副分片放到 ssd 或普通磁盤,可以通過 awareness來實現(xiàn),先為部分節(jié)點配置純 RAM 存儲,配置為hot,其他節(jié)點使用普通存儲,配置為cool,awareness會保證分片的不同副本放到不同區(qū)域,類似 hdfs 的機架感知。但是由于內(nèi)存數(shù)據(jù)容易丟失,最好在寫入過程中將 wait_for_active_shards設(shè)置為 all,讀取的時候通過 preference來控制優(yōu)先讀取 hot 節(jié)點。如果你就想要一個低延遲的搜索,把lucene 文件都加載到內(nèi)存吧!

      還有一種最簡單的是 vmtouch 等方式讓 lucene 文件被系統(tǒng) cache住,但什么時候被清理不可預(yù)期。pagecache 命中率可以用 cachestat來查看,并且對 mmapfs 有效。

      Search Queue 堆積

      如果客戶端發(fā)送的查詢并發(fā)過高,導(dǎo)致 search 線程池占滿,查詢請求進入隊列等待,也會導(dǎo)致查詢過程產(chǎn)生較高延遲。

      定位方式:
      kinaba 中暫時還沒有關(guān)于線程池的指標(biāo),需要自己監(jiān)控

      解決方式:
      控制好客戶端的查詢并發(fā),客戶端的一個查詢請求如果涉及到某個數(shù)據(jù)節(jié)點的三個分片,就會在該節(jié)點占用3個 search 線程。目前指標(biāo)上還看不到請求排隊花費的時間。

      如何解析Elasticsearch的查詢毛刺現(xiàn)象

      題外話:

      es 使用 max_concurrent_shard_requests 參數(shù)來控制單個查詢請求在某個節(jié)點上的查詢并發(fā),避免單個請求把整個集群的查詢資源占滿,協(xié)調(diào)節(jié)點在構(gòu)建完本次查詢請求涉及的目的 shard 列表后,根據(jù) max_concurrent_shard_requests 進行并發(fā)控制,超過并發(fā)的會放入到隊列中,不過這個隊列并不占用 search queue,因此即使并發(fā)受限,其查詢延遲不會受此因素影響。

      總結(jié)

      Lucene 并不是為低延遲而設(shè)計的系統(tǒng),查詢毛刺主要受 GC 和 IO 的影響,GC 層面在于合理的規(guī)劃JVM內(nèi)存,避免頻繁 GC 和 FGC,IO 層面的可以考慮使用 SSD,RAMDISK 或預(yù)留足夠的 pagecache來解決。

      關(guān)于如何解析Elasticsearch的查詢毛刺現(xiàn)象問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。


      網(wǎng)站題目:如何解析Elasticsearch的查詢毛刺現(xiàn)象
      文章源于:http://www.ef60e0e.cn/article/gsgccd.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        兴宁市| 新建县| 东源县| 延安市| 瑞丽市| 绵竹市| 盐池县| 天门市| 安康市| 怀柔区| 封开县| 镇江市| 于都县| 泽库县| 北海市| 浑源县| 祥云县| 红原县| 曲周县| 寿光市| 石柱| 陆丰市| 石泉县| 鹤山市| 卓资县| 黄石市| 新民市| 阿荣旗| 兰溪市| 凉山| 紫阳县| 布拖县| 嵊州市| 柏乡县| 江山市| 武宣县| 南木林县| 盐池县| 吉安市| 榕江县| 桓台县|