介紹
本文是分析Elasticsearch系列文章中的一篇,是一個譯文。共有三篇,每篇講解部分Elasticsearch的實現原理。
在翻譯的過程中,也需要查看對應部分的源碼,來加深對實現原理的理解。但這裏並沒有對源碼進行分析,源碼的分析放到後面的系列文章進行介紹。
本文介紹了Elasticsearch的以下原理:
- 是Master/Slave架構,還是Master-less架構?
- 存儲模型是什麼?
- 寫入操作是如何工作的?
- 讀操作是如何工作的?
- 搜索結果如何相關?
Elasticsearch介紹
Elasticsearch的index
Elasticsearch的索引(index)是用於組織數據的邏輯命名空間(如數據庫)。Elasticsearch的索引有一個或多個分片(shard)(默認爲5)。分片是實際存儲數據的Lucene索引,它本身就是一個搜索引擎。每個分片可以有零個或多個副本(replicas)(默認爲1)。Elasticsearch索引還具有“類型”(如數據庫中的表),允許您在索引中對數據進行邏輯分區。Elasticsearch索引中給定“類型”中的所有文檔(documents)具有相同的屬性(如表的模式)。
圖a顯示了一個由三個主分片組成的Elasticsearch集羣,每個主分片分別有一個副本。所有這些分片一起形成一個Elasticsearch索引,每個分片是Lucene索引本身。
圖b演示了Elasticsearch索引,分片,Lucene索引和文檔(document)之間的邏輯關係。
類比關係數據庫術語
- Elasticsearch Index ~ Database
- Types ~ Tables
- Mapping ~ Schema
Elasticsearch集羣的節點類型
Elasticsearch的一個實例是一個節點,一組節點形成一個集羣。Elasticsearch集羣中的節點可以通過三種不同的方式進行配置:
Master節點
- Master節點控制Elasticsearch集羣,並負責在集羣範圍內創建/刪除索引,跟蹤哪些節點是集羣的一部分,並將分片分配給這些節點。主節點一次處理一個集羣狀態,並將狀態廣播到所有其他節點,這些節點需要響應並確認主節點的信息。
- 在elasticsearch.yml中,將nodes.master屬性設置爲true(默認),可以將節點配置爲有資格成爲主節點的節點。
- 對於大型生產集羣,建議擁有一個專用主節點來控制集羣,並且不服務任何用戶請求。
Data節點
- 數據節點用來保存數據和倒排索引。默認情況下,每個節點都配置爲一個data節點,並且在elasticsearch.yml中將屬性node.data設置爲true。如果您想要一個專用的master節點,那麼將node.data屬性更改爲false。
Client節點
如果將node.master和node.data設置爲false,則將節點配置爲客戶端節點,並充當負載平衡器,將傳入的請求路由到集羣中的不同節點。
若你連接的是作爲客戶端的節點,該節點稱爲協調節點(coordinating node)。協調節點將客戶機請求路由到集羣中對應分片所在的節點。對於讀取請求,協調節點每次選擇不同的分片來提供請求以平衡負載。
在我們開始審查發送到協調節點的CRUD請求如何通過集羣傳播並由引擎執行之前,讓我們看看Elasticsearch如何在內部存儲數據,以低延遲爲全文搜索提供結果。
存儲模型
Elasticsearch使用Apache Lucene,它是由Java編寫的全文搜索庫,由Doug Cutting(Apache Hadoop的創建者)內部開發,它使用稱爲倒排索引的數據結構,用於提供低延遲搜索結果。
文檔(document)是Elasticsearch中的數據單位,並通過對文檔中的術語進行標記來創建倒排索引,創建所有唯一術語的排序列表,並將文檔列表與可以找到該詞的位置相關聯。
它非常類似於一本書背面的索引,其中包含書中的所有獨特的單詞和可以找到該單詞的頁面列表。當我們說一個文檔被索引時,我們引用倒排索引。我們來看看下面兩個文檔的倒排索引如何看待:
如果我們想要找到包含術語“insight”的文檔,我們可以掃描倒排的索引(在哪裏排序),找到“insight”這個詞,並返回包含這個單詞的文檔ID,這在這種情況下將是文檔1和Doc 2號文件。
爲了提高可搜索性(例如,爲小寫字母和小寫字提供相同的結果),首先分析文檔並對其進行索引。
分析由兩部分組成:
- 將句子標記成單詞
- 將單詞規範化爲標準表單
默認情況下,Elasticsearch使用標準分析器 - 標準標記器(Standard tokenizer),用於在單詞邊界上分割單詞
- 小寫令牌過濾器(Lowercase token filter)將單詞轉換爲小寫
還有許多其他分析儀可用,您可以在文檔中閱讀它們。
注意:標準分析儀也使用停止令牌過濾器,但默認情況下禁用。
實現原理分析
write(寫)/create(創建)操作實現原理
當您向協調節點發送請求以索引新文檔時,將執行以下操作:
所有在Elasticsearch集羣中的節點都包含:有關哪個分片存在於哪個節點上的元數據。協調節點(coordinating node)使用文檔ID(默認)將文檔路由到對應的分片。Elasticsearch將文檔ID以murmur3作爲散列函數進行散列,並通過索引中的主分片數量進行取模運算,以確定文檔應被索引到哪個分片。
shard = hash(document_id) % (num_of_primary_shards)
當節點接收到來自協調節點的請求時,請求被寫入到translog(我們將在後續的post中間講解translog),並將該文檔添加到內存緩衝區。如果請求在主分片上成功,則請求將並行發送到副本分片。只有在所有主分片和副本分片上的translog被fsync’ed後,客戶端纔會收到該請求成功的確認。
- 內存緩衝區以固定的間隔刷新(默認爲1秒),並將內容寫入文件系統緩存中的新段。此分段的內容更尚未被fsync’ed(未被寫入文件系統),分段是打開的,內容可用於搜索。
- translog被清空,並且文件系統緩存每隔30分鐘進行一次fsync,或者當translog變得太大時進行一次fsync。這個過程在Elasticsearch中稱爲flush。在刷新過程中,內存緩衝區被清除,內容被寫入新的文件分段(segment)。當文件分段被fsync’ed並刷新到磁盤,會創建一個新的提交點(其實就是會更新文件偏移量,文件系統會自動做這個操作)。舊的translog被刪除,一個新的開始。
- 下圖顯示了寫入請求和數據流程:
Update和Delete實現原理
刪除和更新操作也是寫操作。但是,Elasticsearch中的文檔是不可變的(immutable),因此不能刪除或修改。那麼,如何刪除/更新文檔呢?
磁盤上的每個分段(segment)都有一個.del文件與它相關聯。當發送刪除請求時,該文檔未被真正刪除,而是在.del文件中標記爲已刪除。此文檔可能仍然能被搜索到,但會從結果中過濾掉。當分段合併時(我們將在後續的帖子中包括段合併),在.del文件中標記爲已刪除的文檔不會被包括在新的合併段中。
現在,我們來看看更新是如何工作的。創建新文檔時,Elasticsearch將爲該文檔分配一個版本號。對文檔的每次更改都會產生一個新的版本號。當執行更新時,舊版本在.del文件中被標記爲已刪除,並且新版本在新的分段中編入索引。舊版本可能仍然與搜索查詢匹配,但是從結果中將其過濾掉。
indexed/updated文檔後,我們希望執行搜索請求。我們來看看如何在Elasticsearch中執行搜索請求。
Read的實現原理
讀操作由兩個階段組成:
- 查詢階段(Query Phase)
- 獲取階段(Fetch Phase)
查詢階段(Query Phase)
在此階段,協調節點將搜索請求路由到索引(index)中的所有分片(shards)(包括:主要或副本)。分片獨立執行搜索,並根據相關性分數創建一個優先級排序結果(稍後我們將介紹相關性分數)。所有分片將匹配的文檔和相關分數的文檔ID返回給協調節點。協調節點創建一個新的優先級隊列,並對全局結果進行排序。可以有很多文檔匹配結果,但默認情況下,每個分片將前10個結果發送到協調節點,協調創建優先級隊列,從所有分片中分選結果並返回前10個匹配。
獲取階段(Fetch Phase)
在協調節點對所有結果進行排序,已生成全局排序的文檔列表後,它將從所有分片請求原始文檔。
所有的分片都會豐富文檔並將其返回到協調節點。
如上所述,搜索結果按相關性排序。我們來回顧一下相關性的定義。
搜索相關性(Search Relevance)
相關性由Elasticsearch給予搜索結果中返回的每個文檔的分數確定。用於評分的默認算法爲tf / idf(術語頻率/逆文檔頻率)。該術語頻率測量術語出現在文檔中的次數(更高頻率=更高的相關性),逆文檔頻率測量術語在整個索引中出現的頻率佔索引中文檔總數的百分比(更高的頻率
==較少的相關性)。最終得分是tf-idf分數與其他因素(如詞語鄰近度(短語查詢)),術語相似度(用於模糊查詢)等的組合。
參考
https://blog.insightdatascience.com/anatomy-of-an-elasticsearch-cluster-part-i-7ac9a13b05db
https://blog.insightdatascience.com/anatomy-of-an-elasticsearch-cluster-part-ii-6db4e821b571
https://blog.insightdatascience.com/anatomy-of-an-elasticsearch-cluster-part-iii-8bb6ac84488d
https://www.elastic.co/blog/index-vs-type