1. 簡介
Elasticsearch是一個機遇Lucene構建的開源、分散式、RESTful介面全文搜尋引擎。同時,Elasticsearch還是一個分散式文件資料庫,能夠擴充套件至數百個伺服器儲存以處理PB級資料,通常作為複雜搜尋場景的首選利器。
Elasticsearch的優點:
- 橫向可擴充套件性:只需要增加一臺伺服器,配置完畢即可加入叢集。
- 分片機制提供更好的分佈性:同一個索引分成多個分片,類似於HDFS的塊機制,分而治之的方式提升處理效率。
- 高可用:提供複製機制,一個分片可以設定多個副本,在某臺伺服器當機情況下,叢集依舊可以工作,並在當機伺服器重啟後恢復資料。
- 使用簡單:開箱即用,快速搭建搜尋服務。
Elasticsearch wiki:https://zh.wikipedia.org/wiki/Elasticsearch
2. 資料庫搜尋
在資料量少的情況下可以當做搜尋服務來使用,然而資料庫歸根結底是做持久化儲存。如果資料量大就需要做搜尋服務,底層資料還是關聯式資料庫。我司老系統中有一個訂單表,資料量已經高達兩億,客服等後臺系統通常帶有範圍或批量條件等查詢,這時資料庫基本上就無法響應了,報警根本停不下來。因此,用資料庫來實現搜尋,效能差,可用性不高。
3. Lucene
Lucene是一個開源的全文搜尋引擎工具包,其目的是為開發者提供一個簡單工具包,以快速實現全文檢索的功能。
Lucene wiki:https://zh.wikipedia.org/wiki/Lucene
4. 倒排索引
倒排索引中的索引物件是文件或者文件集合中的單詞等,用來儲存這些單詞在一個文件或者一組文件中的儲存位置,是對文件或者文件集合的一種最常用的索引機制。搜尋引擎的關鍵步驟就是建立倒排索引,下面介紹Lucene是如何建立倒排索引和相應的生成演算法。
假設有兩篇文章: 文章1:Tom lives in Guangzhou, I live in Guangzhou too. 文章2:He once lived in Shanghai.
4.1 取得關鍵詞
Lucene是基於關鍵詞索引和查詢的,首先要進行關鍵詞提取:
-
分詞:英文單詞由空格分隔,較好處理;中文詞語由於是連在一起的,需要進行特殊的分詞處理(後面會介紹分詞器相關知識)。
-
過濾無概念詞語:英文中“in”“once”“too”等詞沒有實際意義;中文中“的”“是”等也無實際意義,這些無概念詞語可以過濾掉。
-
統一大小寫:“he”和“HE”表示的含義一樣,所以單詞需要統一大小寫。
-
語義還原:通常使用者查詢“live”時希望能將“lives”和“lived”也查詢出來,所以需要將“lives”和“lived”還原成“live”。
-
過濾標點符號
經過以上過濾,得到如下結果: 文章1關鍵詞:tom live guangzhou i live guangzhou 文章2關鍵詞:he live shanghai
4.2 建立倒排索引
關鍵詞建立完成後,就可以進行倒排索引建立了。過濾後的關係是:“文章號“對”文章中所有關鍵詞“,倒排索引把這個關係倒過來變成:”關鍵詞“對”擁有關鍵詞的所有文章號“。
通常僅知道關鍵詞在哪些文章中出現還不夠,還需要知道關鍵詞在文章中出現的次數和位置,通常有兩種位置:
- 字元位置,即記錄該詞是文章中第幾個字元(優點是顯示並定位關鍵詞快)。
- 關鍵詞位置,即記錄該詞是文章中的第幾個關鍵詞(優點是節約索引空間、片語查詢快),Lucene中記錄的就是這種位置。
以上就是Lucene索引結構中最核心的部分,關鍵字是按字元順序排列的(Lucene沒有使用B樹結構),因此Lucene可以使用二元搜尋演算法快速定位關鍵詞。
4.3 實現
Lucene將上面三列分別作為詞典檔案(Term Dictionary)、頻率檔案(frequencies)、位置檔案(positions)儲存。其中詞典檔案不僅儲存了每個關鍵詞,還保留了指向頻率檔案和位置檔案的指標,通過指標可以找到該關鍵字的頻率資訊和位置資訊。
Lucene中使用了field的概念,用於表達資訊所在的位置(如標題中、文章中、url中),在建索引中,該field資訊也記錄在詞典檔案中,每個關鍵詞都有一個field資訊,因為每個關鍵字一定屬於一個或多個field。
4.4 壓縮演算法
為了減小索引檔案的大小,Lucene對索引還是用了壓縮技術。 首先,對詞典檔案中的關鍵詞進行壓縮,關鍵詞壓縮為<字首長度,字尾>,例如:當前詞為”阿拉伯語“,上一個詞為”阿拉伯“,那麼”阿拉伯語“壓縮為<3,語>。 其次大量用到的是對數字的壓縮,數字只儲存與上一個值的差值(這樣可以減少數字的長度,進而減少儲存該數字需要的位元組數)。例如當前文章號是16389(不壓縮要用3個位元組),上一文章號是16382,壓縮後儲存7(只用一個位元組)。
壓縮演算法推薦閱讀:https://www.cnblogs.com/dreamroute/p/8484457.html
4.5 實戰
查詢單詞”live“,Lucene先對詞典二元查詢,找到該詞,通過指向頻率檔案的指標讀出所有文章號,然後返回結果。詞典通常非常小,可以達到毫秒級返回。而用普通的順序匹配演算法,不建立索引,而是對所有文章的內容進行字串匹配,過程是很緩慢的,當資料量很大時,耗時更加嚴重。
5. 基礎概念
5.1 索引詞(term)
Elasticsearch中能夠被索引的精確值。foo、Foo、FOO幾個單詞是不同的索引詞。索引詞可以通過term查詢進行準確的搜尋。
5.2 文字(text)
文字會被拆分成一個個索引詞儲存在索引庫中,為後續搜尋提供支援。
5.3 分析(analysis)
分析是將文字轉換為索引詞的過程,其結果依賴於分詞器。
5.4 叢集(cluster)
叢集由一個或多個節點組成,對外提供服務。Elasticsearch節點如果有相同的叢集名稱會自動加入到同一個叢集,因此如果你擁有多個獨立叢集,每個叢集都要設定不同的名稱。
5.5 節點(node)
節點是一個邏輯上獨立的服務,是叢集的一部分,可以儲存資料,並參與叢集的索引和搜尋功能。
5.6 路由(routing)
文件儲存時是通過雜湊值進行計算,最終選擇儲存在主分片中,這個值預設是由文件的ID生成。
5.7 分片(shard)
分片是單個Lucene例項,是Elasticsearch管理的比較底層的功能。當索引佔用空間很大超過一個節點的物理儲存,Elasticsearch將索引切分成多個分片,分散在不同的物理節點上,以解決單物理節點儲存空間有限的問題。
5.8 主分片(primary shard)
每個文件都儲存在一個分片中,儲存文件時系統會首先儲存在主分片中,然後複製到不同的副本中。預設情況下一個索引擁有5個主分片,分片一旦建立,主分片數量就無法修改。
5.9 副本分片(replica shard)
每個主分片有零個或多個副本,是主分片的複製,其主要目的是:
- 增加高可用性:當主分片失敗時,某一副本分片提升為主分片
- 提高效能:副本分片數量可以動態配置,可以為主分片分擔查詢壓力。
- 允許水平分割擴充套件資料
- 允許分配和並行操作,從而提高效能和吞吐量。
5.10 複製(replica)
主分片的資料會複製到副本分片中,這樣避免了單點問題,當某個節點發生故障,複製可以對故障進行轉移,保證系統的高可用。
5.11 索引(index)
索引是具有相同結構的文件合集。
5.12 型別(type)
一個索引可以定義一個或多個型別,型別是索引的邏輯分割槽。
5.13 文件(document)
文件是儲存在Elasticsearch中的一個JSON格式的字串,就像關聯式資料庫中表的一行記錄。
5.14 對映(mapping)
對映像關聯式資料庫中的表結構,每個索引都有一個對映,它定義了索引中的每一個欄位型別。對映可以事先被定義,也可以在第一次儲存文件時被自動識別。
5.15 欄位(field)
文件中包含零個或多個欄位,欄位可以是一個簡單的值,也可以是一個陣列或物件的巢狀結構。欄位類似於關聯式資料庫中表的列,每個欄位都對應一個欄位型別。
5.16 來源欄位(source field)
預設情況下源文件將被儲存在_source欄位中,查詢時返回該欄位。
5.17 主鍵(ID)
ID是檔案的唯一標識,如果未指定,系統會自動生成一個ID,文件的index/type/id必須是唯一的。
5.18 Elasticsearch核心概念 vs. 資料庫核心概念
Elasticsearch | 資料庫 |
---|---|
Document | row 行 |
Type | table 表 |
Index | database 庫 |
Tips
本文同步發表在公眾號,歡迎大家關注!? 後續筆記歡迎關注獲取第一時間更新!