自底向上分析Elasticsearch

來源:互聯網
上載者:User

原文部落格連結
    這個系列文章裡,我們將用一個新的視角去剖析Elasticsearch。我們先從一些底部的抽象層開始,逐步上移至使用者視角。期間會學習Elasticsearch內部的資料結構和行為。

介紹 倒排索引和詞項 建立索引 索引段index segment Elasticsearch索引 事務 總結

介紹

    這篇文章的目的為了更好的理解Elasticsearch,Lucene等搜尋引擎是如果工作。開車的時候,你只需要把車子啟動起來,踩踩踏板就OK,但“老司機”還會對汽車的基本原理有所瞭解。對於搜尋引擎同樣如此。Elasticsearch提供了簡單易用的API,通過這些API能滿足大多數需要。但想最大限度的利用Elasticsearch,瞭解其底層的演算法和資料結構很有必要。

    我們從最基本的倒排索引開始。倒排索引是個非常有用的資料結構,並且簡潔易懂。Lucene是一個高度最佳化的倒排索引實現,但這裡不會深入到Lucene的實現細節,先來看倒排索引是如何構建和使用的。這個過程會影響搜尋和索引文檔

    將倒排索引作為抽象層的底部,我們會討論: 一個簡單的搜尋是如何進行的 什麼類型的搜尋能夠(或不能夠)有效執行,以及為什麼會這樣。使用倒排索引時,我們會將問題轉化為字串首碼匹配問題 為什麼文本處理很重要 索引是如何在segment重構建,以及如何影響搜尋和更新 Lucene索引的組成 Elasticsearch中的分區和索引

    從這個點看,我們將學習到在單個Elasticsearch節點中搜尋和索引時發生了什麼。在這個系列的第二篇文章中會介紹Elasticsearch如何處理分布式管理。 倒排索引和詞項

    我們有三個簡單的文檔:”Winter is coming.”, “Ours is the fury.”和 “The choice is yours.”。經過一些簡單的文本處理(字母小寫化,去除標點符號和切詞),我們可以組織一個上圖所示的倒排索引。

    倒排索引將詞項映射到包含該詞項的文檔(如果可能的話,還指明詞項在文檔中出現的位置)。因為詞項儲存在單詞詞典中(dictionary),所以我們可以很快的找到該詞項,進而找到單詞在文檔中是否出現的資訊(postings)。這些資訊儲存在一個相反的結構中——正排索引。正排索引記錄了和與詞項關聯的文檔。

    一個簡單的多詞項搜尋過程:首先在單詞詞典尋找所有詞項,以及詞項對應的出現資訊,然後對出現文檔集合取交集(對於and索索)或者並集(對於or搜尋)操作,得到最後的結果文檔集合。複雜的搜尋也涉及到的過程也基本相同。

    因此一個索引詞項是一個搜尋單元,我們產生的詞項決定哪些搜尋能夠(或不能夠)高效的進行。例如,就上面的詞項詞典,我們可以很快找到所有”c”開頭的詞項。但是我們不能很快找到所有包含”ours”的詞項。為了找到所有包含”ours”的詞項,我們不得不遍曆所有詞項,並且還會找到”yours”這種詞項。除非索引很小,否則這類操作會帶來很高的消耗。就複雜度而言,通過首碼尋找詞項的複雜度 (O(log(n))) (\mathcal{O}\left(\mathrm{log}\left(n\right)\right)),而從任意位置開始的子串尋找複雜度 (O(n)) (\mathcal{O}\left(n\right))

    換句話說,通過首碼串,我們可以非常有效找到需要的詞項。當我們有倒排索引時,我們希望所有的尋找都是首碼串問題。這裡有幾個例子能做出這種轉換,有一些比較簡單,最後一個近乎魔法。 為了找到所有以”tastic”結尾的詞,我們可以索引詞項的反轉(例如”fantastic” → “citsatnaf”),然後對每個詞項詞典中的詞作反轉後的首碼尋找 子串查詢通常包含詞項切割,例如”yours”被切割成”^yo”,”you”,”our”,”urs”,”rs$”。所以當我們的尋找”our”或”urs”的時候,能找到”your”的出現資訊 對於有合成詞的語言,例如Norwegian和German,我們需要“分解”詞項。例如”Donaudampfschiff”分解成{“donau”, “dampf”, “schiff”}。 地理座標被轉化為”地理hash“,例如(60.6384, 6.5017)被轉化為”u4u8gyykk”,字串越長越精確 音標匹配對人名非常有效,像Metaphone的演算法將”Smith”轉化成{“SM0”, “XMT”} 處理數值型和時間戳記資料時,Lucene自動產生幾個不同精度的詞項,組成首碼儲存類型,所以範圍搜尋非常高效。簡單來講,數字123被儲存成”1”個百,”12”個十和”123”。至此,搜尋所有[100,199]變成了尋找所有”1”個百的詞項。這和查詢以”1”開頭的詞項不同,因為這樣的搜尋會包含例如”1234” 為了做類似”Did you mean”這樣的搜尋並且找到相似的拼字,在遍曆詞項字典的時候,編輯距離也需要建立。這個操作非常複雜,好在一切都在Lucene裡被完成

    對文本處理的深入理解是後續文章的基礎,我們還強調了為什麼文本處理對於產生索引詞項如此重要:為了更高效的搜尋。 建立索引

    建立索引時,有幾件事情需要事先考慮:搜尋速度,索引密度,索引文檔的速度,以及索引文檔或更新文檔之後到這些變化可以被搜尋到的時間。

    搜尋速度和索引密度相互關聯:搜尋的索引越小,需要處理的資料越少,就有更適應於記憶體操作。而壓縮會操作會在索引文檔階段產生消耗一定的時間消耗。

    為了壓縮化索引大小,有多種壓縮技術可以選擇。例如為了儲存詞項和文檔的關係(前文的postings,它可能會非常大),Lucene採取查分編碼([42, 100, 666]被儲存成[42, 58, 566]),變長位元組儲存(小數字可以用一個位元組儲存)等方式。

    縮小&壓縮資料存放區意味著犧牲快速更新的能力。事實上,Lucene的索引檔案都不可變檔案,因此並沒有更新操作。這與B樹這種能夠進行更新操作和制定更新量的資料結構不同。

    刪除也和通常想的不同。當刪除索引中的文檔時,只是在bitmap中更新了一下,標誌這個文檔被刪除了。而索引結構本身並沒有任何更新。

    相應的更新一個索引文檔需要先刪除,然後重新插入更新後的文檔。因此更新文檔比插入文檔的效能消耗要高。在Lucene中儲存頻繁變化的值並不合適,因為這裡沒有就地更新。

    當新加入文檔時(可能是通過更新),索引的變化會先緩衝到記憶體中。最終才被完整的刷到磁碟。需要注意的是,這裡的“重新整理”是Lucene意義上的重新整理,Elasticsearch的重新整理操作包括Lucene的提交和其他動作,這些操作會被記錄到交易記錄中。

    重新整理產生的時機取決於幾個因素:變化被可見的速度,用於緩衝的記憶體大小,I/O飽和度等。通常來說,對於索引文檔的速度而言,只要你的I/O系統能跟得上重新整理,緩衝越大越好。下一節我們會更加詳細的描述。

    這些被寫入的檔案組成索引段。 索引段(index segment)

    Lucene索引有一個或多個不可變的索引段組成,索引段本身可以看作一個”迷你索引“。搜尋時,Lucene在每個索引段上做搜尋,過濾掉刪除的文檔,然後合并所有索引段的結果。當索引段數量變多時,也就存在了更多的冗餘。為了把索引段的數量控制在一個方便管理的範圍,Lucene會根據合并策略把索引段合并成新索引段。Lucene大咖Michael McCandless對此有索引合并有一個很好的視頻解釋。在索引段合并的時候,被標記刪除的文檔才真正被刪除。所以有時候新加入文檔反而得到一個更小的索引:因為合并而瘦身。

    Elasticsearch和Lucene通常在處理索引段合并時做的很好。Elasticsearch的合并策略可以通過修改合并設定來改變。你也可以使用optimize-API來強制合并。

    索引段被寫入到磁碟之前,修改都緩衝在記憶體。以前(Lucene版本小於2.3)每個新增加的文檔在記憶體中都有一個自己的微型索引段,只有在寫入磁碟時才合并。現在,通過DocumentsWriter,記憶體中可以將多篇文檔做成一個較大的索引段。在Lucene 4裡,每一個線程裡都有一個DocumentsWriter,通過兵法寫入的方式提高索引文檔的效能。(以前索引文檔必須等到寫入磁碟結束)

    當一個新的索引段產生的時候(不管是新寫入還是合并),必定引起某些緩衝失效,這影響搜尋效能。緩衝(例如欄位緩衝和過濾器緩衝)和索引段綁定,一個索引段有幾個不同的緩衝。Elasticsearch有個warmer-API。必要的緩衝可以在新索引段可供查詢前準備好。

    最常見的因為Elasticsearch引起的寫入磁碟可能由於連續索引文檔而產生的重新整理。這個操作預設每秒一次。當新的索引段被寫入磁碟,他們就能被搜尋。儘管flush沒有commit如此消耗效能(因為flush不用等待寫入確認),但它會建立新的索引段,使某些緩衝失效,並且可能觸發一次合并。

    如果索引文檔的吞吐很重要,例如批量索引文檔,花費太多時間flush以及合并小索引段會變得很浪費。這種情況下,暫時把refresh_interval設定得大一點,或者禁止自動refresh會是個好主意。當索引文檔結束時,手動refresh總是可行。 Elasticsearch索引

“All problems in computer science can be solved by another level of indirection.” – David J. Wheeler

    Elasticsearch的索引由一個或多個分區組成,每一個分區有零至多個副本。這些分區都是單獨的Lucene索引。也就是說,每一個Elasticsearch索引由多個Lucene索引組成,而每一個Lucene索引又由多個索引段組成。當搜尋一個Elasticsearch索引時,會在所有的分區上執行,也就是在所有的索引段上執行,最後把結果合并。對於搜尋多個Elasticsearch索引也是一樣。事實上,搜尋兩個只有一個分區的Elasticsearch索引和搜尋一個有兩個分區的索引幾乎一樣。兩者都搜尋了兩個Lucene索引。

    從這個點開始,後面所有的“索引”都是指Elasticsearch的索引。

    分區是Elasticsearch中最基本的容量縮放單位。當文檔被添加到索引裡,文檔會被路由到一個分區。預設情況下,會根據文檔id的hash值做round-robin演算法。在這個系列的第二篇文章裡,我們會看到更多分區的運作機制。要注意的是,分區數在建立索引時已經確定並且之後不能修改。在一次Shay的Elasticsearch分享中很好的解釋了為什麼一個分區就是一個完整的Lucene索引,解釋了這種方式的優點,並且說明了和別的方式比較時所作的權衡。

    Elasticsearch的搜尋非常靈活,能夠指定索引和分區。索引名模板,索引別名和搜尋路由,很多資料流策略能夠使用。這裡我們不會展開去講,在此推薦Zachary Tong的文章《customizing document routing》和Shay Banon的分享《big data, search and analytics》。一下的例子可能會有一點啟發: 基於時間的資料,例如日誌,每天(或每周,每月)建立一個索引,我們能有效限制搜尋時間範圍,並且很容易刪除舊資料。雖然從索引裡刪除文檔很麻煩,但是刪除整個索引成本卻很低。 當必須限定某個使用者的搜尋時,把那個使用者的所有文檔路由到同一個分區會非常有用,這樣會減少搜尋的分區。 事務

    儘管Lucene有事務的概念,但Elasticsearch卻沒有。所有的Elasticsearch操作被加到同一個時間軸,這個時間軸不需要貫穿所有節點,因為flush操作依賴各個節點的時機。

    管理分布式系統中不同節點,不同分區中的索引段,緩衝非常困難。與其去做這個管理,不如怎麼把系統做更快。

    Elasticsearch有交易記錄(transaction log),用於追加記錄被索引的文檔。追加一個文檔比建立索引段要簡單得多,所以Elasticsearch能將文檔持久化,同時還寫到記憶體緩衝中。你可以在索引文檔時候指定一致性層級。例如可以指定每個副本都索引好文檔之後才返回索引文檔操作。 總結

    總結起來,Lucene在建立,更新,搜尋單個索引時有這麼幾個重要的屬性需要注意 我們如何處理文本決定我們可以怎麼搜尋。合適的文本分析很重要。 索引現在記憶體中建立,然後被flush到磁碟中的索引段。 索引段不可變,刪除文檔只是被標記刪除 一個索引由很多索引段組成,搜尋操作在每個索引段上執行,然後合并結果 索引段的合并時不時就發生,依賴時機 每個索引段都有欄位緩衝和過濾器緩衝 Elasticsearch沒有事務

在這個系列的下一篇文章裡,我們會看看搜尋和索引文檔操作如何在叢集中執行。

參考連結:
[1]https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up
[2]http://lucene.apache.org/core/4_4_0/core/overview-summary.html
[3]http://blog.trifork.com/2011/04/01/gimme-all-resources-you-have-i-can-use-them/
[4]http://blog.mikemccandless.com/2011/02/visualizing-lucenes-segment-merges.html
[5]https://www.elastic.co/blog/customizing-your-document-routing

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.