圖解ElasticSearch 搜索原理!看完就明白了

先自上而下,後自底向上的介紹ElasticSearch的底層工做原理,試圖回答如下問題:html

  • 爲何個人搜索 *foo-bar* 沒法匹配 foo-bar
  • 爲何增長更多的文件會壓縮索引(Index)?
  • 爲何ElasticSearch佔用不少內存?

版本

elasticsearch版本: elasticsearch-2.2.0緩存

雲上的集羣

圖片

集羣裏的盒子

雲裏面的每一個白色正方形的盒子表明一個節點——Node。網絡

圖片

節點之間

在一個或者多個節點直接,多個綠色小方塊組合在一塊兒造成一個ElasticSearch的索引。數據結構

圖片

索引裏的小方塊

在一個索引下,分佈在多個節點裏的綠色小方塊稱爲分片——Shard。elasticsearch

圖片

Shard=Lucene Index

一個ElasticSearch的Shard本質上是一個Lucene Index。這篇 ElasticSearch 詳細使用教程,內部分享時被老大表揚了性能

圖片

Lucene是一個Full Text 搜索庫(也有不少其餘形式的搜索庫),ElasticSearch是創建在Lucene之上的。接下來的故事要說的大部份內容其實是ElasticSearch如何基於Lucene工做的。超詳細 116 頁 Elasticsearch 實戰文檔!高清可下載優化

圖解Lucene

Mini索引——segment

在Lucene裏面有不少小的segment,咱們能夠把它們當作Lucene內部的mini-index。spa

圖片

Segment內部

有着許多數據結構3d

  • Inverted Index
  • Stored Fields
  • Document Values
  • Cache

圖片

最最重要的Inverted Index

圖片

Inverted Index主要包括兩部分:日誌

  • 一個有序的數據字典Dictionary(包括單詞Term和它出現的頻率)。
  • 與單詞Term對應的Postings(即存在這個單詞的文件)。

當咱們搜索的時候,首先將搜索的內容分解,而後在字典裏找到對應Term,從而查找到與搜索相關的文件內容。Elasticsearch 查詢數據的工做原理是什麼?

圖片

查詢「the fury」

圖片

自動補全(AutoCompletion-Prefix)

若是想要查找以字母「c」開頭的字母,能夠簡單的經過二分查找(Binary Search)在Inverted Index表中找到例如「choice」、「coming」這樣的詞(Term)。ElasticSearch 億級數據檢索案例實戰!

圖片

昂貴的查找

若是想要查找全部包含「our」字母的單詞,那麼系統會掃描整個Inverted Index,這是很是昂貴的。

圖片

在此種狀況下,若是想要作優化,那麼咱們面對的問題是如何生成合適的Term。

問題的轉化

圖片

對於以上諸如此類的問題,咱們可能會有幾種可行的解決方案:

* suffix -> xiffus *

若是咱們想之後綴做爲搜索條件,能夠爲Term作反向處理。

(60.6384, 6.5017) -> u4u8gyykk

對於GEO位置信息,能夠將它轉換爲GEO Hash。

123 -> {1-hundreds, 12-tens, 123}

對於簡單的數字,能夠爲它生成多重形式的Term。

解決拼寫錯誤

一個Python庫 爲單詞生成了一個包含錯誤拼寫信息的樹形狀態機,解決拼寫錯誤的問題。

圖片

Stored Field字段查找

當咱們想要查找包含某個特定標題內容的文件時,Inverted Index就不能很好的解決這個問題,因此Lucene提供了另一種數據結構Stored Fields來解決這個問題。本質上,Stored Fields是一個簡單的鍵值對key-value。默認狀況下,ElasticSearch會存儲整個文件的JSON source。

圖片

Document Values爲了排序,聚合

即便這樣,咱們發現以上結構仍然沒法解決諸如:排序、聚合、facet,由於咱們可能會要讀取大量不須要的信息。

因此,另外一種數據結構解決了此種問題:Document Values。這種結構本質上就是一個列式的存儲,它高度優化了具備相同類型的數據的存儲結構。

圖片

爲了提升效率,ElasticSearch能夠將索引下某一個Document Value所有讀取到內存中進行操做,這大大提高訪問速度,可是也同時會消耗掉大量的內存空間。

總之,這些數據結構Inverted Index、Stored Fields、Document Values及其緩存,都在segment內部。

搜索發生時

搜索時,Lucene會搜索全部的segment而後將每一個segment的搜索結果返回,最後合併呈現給客戶。

Lucene的一些特性使得這個過程很是重要:

  • Segments是不可變的(immutable)
  • Delete? 當刪除發生時,Lucene作的只是將其標誌位置爲刪除,可是文件仍是會在它原來的地方,不會發生改變
  • Update? 因此對於更新來講,本質上它作的工做是:先刪除,而後從新索引(Re-index)
  • 隨處可見的壓縮
  • Lucene很是擅長壓縮數據,基本上全部教科書上的壓縮方式,都能在Lucene中找到。
  • 緩存全部的全部
  • Lucene也會將全部的信息作緩存,這大大提升了它的查詢效率。
緩存的故事

當ElasticSearch索引一個文件的時候,會爲文件創建相應的緩存,而且會按期(每秒)刷新這些數據,而後這些文件就能夠被搜索到。

圖片

隨着時間的增長,咱們會有不少segments,

圖片

因此ElasticSearch會將這些segment合併,在這個過程當中,segment會最終被刪除掉

圖片

這就是爲何增長文件可能會使索引所佔空間變小,它會引發merge,從而可能會有更多的壓縮。

舉個栗子

有兩個segment將會merge

圖片

這兩個segment最終會被刪除,而後合併成一個新的segment

圖片

這時這個新的segment在緩存中處於cold狀態,可是大多數segment仍然保持不變,處於warm狀態。

以上場景常常在Lucene Index內部發生的。

圖片

在Shard中搜索

ElasticSearch從Shard中搜索的過程與Lucene Segment中搜索的過程相似。

圖片

與在Lucene Segment中搜索不一樣的是,Shard多是分佈在不一樣Node上的,因此在搜索與返回結果時,全部的信息都會經過網絡傳輸。

須要注意的是:

1次搜索查找2個shard = 2次分別搜索shard

圖片

對於日誌文件的處理

當咱們想搜索特定日期產生的日誌時,經過根據時間戳對日誌文件進行分塊與索引,會極大提升搜索效率。

當咱們想要刪除舊的數據時也很是方便,只需刪除老的索引便可。

圖片

在上種狀況下,每一個index有兩個shards

如何Scale

圖片

shard不會進行更進一步的拆分,可是shard可能會被轉移到不一樣節點上

圖片

因此,若是當集羣節點壓力增加到必定的程度,咱們可能會考慮增長新的節點,這就會要求咱們對全部數據進行從新索引,這是咱們不太但願看到的,因此咱們須要在規劃的時候就考慮清楚,如何去平衡足夠多的節點與不足節點之間的關係。

節點分配與Shard優化
  • 爲更重要的數據索引節點,分配性能更好的機器
  • 確保每一個shard都有副本信息replica

圖片

路由Routing

每一個節點,每一個都存留一份路由表,因此當請求到任何一個節點時,ElasticSearch都有能力將請求轉發到指望節點的shard進一步處理。

圖片

一個真實的請求

圖片

Query

圖片

Query有一個類型filtered,以及一個multi\_match的查詢

Aggregation

圖片

根據做者進行聚合,獲得top10的hits的top10做者的信息

請求分發

這個請求可能被分發到集羣裏的任意一個節點

圖片

上帝節點

圖片

這時這個節點就成爲當前請求的協調者(Coordinator),它決定:

  • 根據索引信息,判斷請求會被路由到哪一個核心節點
  • 以及哪一個副本是可用的
  • 等等
路由

圖片

在真實搜索以前

ElasticSearch 會將Query轉換成Lucene Query

圖片

而後在全部的segment中執行計算

圖片

對於Filter條件自己也會有緩存

圖片

但queries不會被緩存,因此若是相同的Query重複執行,應用程序本身須要作緩存

圖片

因此,

  • filters能夠在任什麼時候候使用
  • query只有在須要score的時候才使用
返回

搜索結束以後,結果會沿着下行的路徑向上逐層返回。

圖片

圖片

圖片

圖片

圖片

來源:https://www.cnblogs.com/richa...

相關文章
相關標籤/搜索