Elasticsearch Lucene 資料寫入原理 | ES 核心篇

泥瓦匠發表於2019-08-16

前言

最近 TL 分享了下 《Elasticsearch基礎整理》,蹭著這個機會。寫個小文鞏固下,本文主要講 ES -> Lucene
的底層結構,然後詳細描述新資料寫入 ES 和 Lucene 的流程和原理。這是基礎理論知識,整理了一下,希望能對 Elasticsearch 感興趣的同學有所幫助。

一、Elasticsearch & Lucene 是什麼

圖片描述

什麼是 Elasticsearch ?
Elasticsearch 是一個基於 Apache Lucene(TM) 的開源搜尋引擎。

那 Lucene 是什麼?
無論在開源還是專有領域,Lucene 可以被認為是迄今為止最先進、效能最好的、功能最全的搜尋引擎庫,並通過簡單的 RESTful API 來隱藏 Lucene 的複雜性,從而讓全文搜尋變得簡單。

Elasticsearch 不僅僅是 Lucene 和全文搜尋,我們還能這樣去描述它:

  • 分散式的實時檔案儲存,每個欄位都被索引並可被搜尋
  • 分散式的實時分析搜尋引擎
  • 可以擴充套件到上百臺伺服器,處理 PB 級結構化或非結構化資料

二、Elasticsearch & Lucene 的關係

圖片描述

就像很多業務系統是基於 Spring 實現一樣,Elasticsearch 和 Lucene 的關係很簡單:Elasticsearch 是基於 Lucene 實現的。ES 基於底層這些包,然後進行了擴充套件,提供了更多的更豐富的查詢語句,並且通過 RESTful API 可以更方便地與底層互動。類似 ES 還有 Solr 也是基於 Lucene 實現的。

在應用開發中,用 Elasticsearch 會很簡單。但是如果你直接用 Lucene,會有大量的整合工作。

因此,入門 ES 的同學,稍微瞭解下 Lucene 即可。如果往高階走,還是需要學習 Lucene 底層的原理。因為倒排索引、打分機制、全文檢索原理、分詞原理等等,這些都是不會過時的技術。

三、新文件寫入流程

3.1 資料模型

圖片描述

如圖

  • 一個 ES Index (索引,比如商品搜尋索引、訂單搜尋索引)叢集下,有多個 Node (節點)組成。每個節點就是 ES 的例項。
  • 每個節點上會有多個 shard (分片), P1 P2 是主分片 R1 R2 是副本分片
  • 每個分片上對應著就是一個 Lucene Index(底層索引檔案)
  • Lucene Index 是一個統稱。由多個 Segment (段檔案,就是倒排索引)組成。每個段檔案儲存著就是 Doc 文件。

3.2 Lucene Index

圖片描述

lucene 中,單個倒排索引檔案稱為 segment。其中有一個檔案,記錄了所有 segments 的資訊,稱為 commit point:

  • 文件 create 新寫入時,會生成新的 segment。同樣會記錄到 commit point 裡面
  • 文件查詢,會查詢所有的 segments
  • 當一個段存在文件被刪除,會維護該資訊在 .liv 檔案裡面

3.3 新文件寫入流程

新文件建立或者更新時,進行如下流程:

更新不會修改原來的 segment,更新和建立操作都會生成新的一個 segment。資料哪裡來呢?先會存在記憶體的 bugger 中,然後持久化到 segment 。

資料持久化步驟如下:write -> refresh -> flush -> merge

3.3.1 write 過程

圖片描述

一個新文件過來,會儲存在 in-memory buffer 記憶體快取區中,順便會記錄 Translog。

這時候資料還沒到 segment ,是搜不到這個新文件的。資料只有被 refresh 後,才可以被搜尋到。那麼 講下 refresh 過程

3.3.2 refresh 過程

圖片描述

refresh 預設 1 秒鐘,執行一次上圖流程。ES 是支援修改這個值的,通過 index.refresh_interval 設定 refresh (沖刷)間隔時間。refresh 流程大致如下:

  • in-memory buffer 中的文件寫入到新的 segment 中,但 segment 是儲存在檔案系統的快取中。此時文件可以被搜尋到
  • 最後清空 in-memory buffer。注意: Translog 沒有被清空,為了將 segment 資料寫到磁碟

文件經過 refresh 後, segment 暫時寫到檔案系統快取,這樣避免了效能 IO 操作,又可以使文件搜尋到。refresh 預設 1 秒執行一次,效能損耗太大。一般建議稍微延長這個 refresh 時間間隔,比如 5 s。因此,ES 其實就是準實時,達不到真正的實時。

3.3.3 flush 過程

圖片描述

上個過程中 segment 在檔案系統快取中,會有意外故障文件丟失。那麼,為了保證文件不會丟失,需要將文件寫入磁碟。那麼文件從檔案快取寫入磁碟的過程就是 flush。寫入次怕後,清空 translog。

translog 作用很大:

  • 保證檔案快取中的文件不丟失
  • 系統重啟時,從 translog 中恢復
  • 新的 segment 收錄到 commit point 中

具體可以看官方文件:https://www.elastic.co/guide/...

3.3.4 merge 過程

圖片描述

圖片描述

上面幾個步驟,可見 segment 會越來越多,那麼搜尋會越來越慢?怎麼處理呢?

通過 merge 過程解決:

  • 就是各個小段檔案,合併成一個大段檔案。段合併過程
  • 段合併結束,舊的小段檔案會被刪除
  • .liv 檔案維護的刪除文件,會通過這個過程進行清除

四、小結

圖片描述

如這個圖,ES 寫入原理不難,記住關鍵點即可。

write -> refresh -> flush

  • write:文件資料到記憶體快取,並存到 translog
  • refresh:記憶體快取中的文件資料,到檔案快取中的 segment 。此時可以被搜到
  • flush 是快取中的 segment 文件資料寫入到磁碟

寫入的原理告訴我們,考慮的點很多:效能、資料不丟失等等

(完)

參考資料:

相關文章