1. 程式人生 > >elasticsearch學習筆記--原理介紹

elasticsearch學習筆記--原理介紹

restfu 及其 觸發 com 相似之處 mpi fsync rip 開源代碼

前言:上一篇中我們對ES有了一個比較大概的概念,知道它是什麽,幹什麽用的,今天給大家主要講一下他的工作原理

介紹ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放源碼發布,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。

揭面

技術分享

架構圖

技術分享

架構各模塊介紹


Lucence Directory: 是lucene的框架服務發現以及選主 ZenDiscovery: 用來實現節點自動發現,還有Master節點選取,假如Master出現故障,其它的這個節點會自動選舉,產生一個新的Master


Plugins:插件可以通過自定的方式擴展加強Elasticsearch的基本功能,比如可以自定義類型映射,分詞器,本地腳本,自動發現等
Scripting:使用腳本語言可以計算自定義表達式的值,比如計算自定義查詢相關度評分。
支持的腳本語言有groovy,js,mvel(1.3.0廢棄),python等
Disovery:該模塊主要負責集群中節點的自動發現和Master節點的選舉。節點之間使用p2p的方式進行直接通信,不存在單點故障的問題。Elasticsearch中,Master節點維護集群的全局狀態,比如節點加入和離開時進行shard的重新分配
River:代表es的一個數據源,也是其它存儲方式(如:數據庫)同步數據到es的一個方法。它是以插件方式存在的一個es服務,通過讀取river中的數據並把它索引到es中

Gateway:模塊用於存儲es集群的元數據信息。
Zen Discovery :zen發現機制是elasticsearch默認的內建模塊。它提供了多播和單播兩種發現方式,能夠很容易的擴展至雲環境。zen發現機制是和其他模塊集成的,例如所有節點間通訊必須用trasport模塊來完成。

核心概念

集群(Cluster): ES集群是一個或多個節點的集合,它們共同存儲了整個數據集,並提供了聯合索引以及可跨所有節點的搜索能力。多節點組成的集群擁有冗余能力,它可以在一個或幾個節點出現故障時保證服務的整體可用性。
集群靠其獨有的名稱進行標識,默認名稱為“elasticsearch”。節點靠其集群名稱來決定加入哪個ES集群,一個節點只能屬一個集群。


節點(node): 一個節點是一個邏輯上獨立的服務,可以存儲數據,並參與集群的索引和搜索功能, 一個節點也有唯一的名字,群集通過節點名稱進行管理和通信.
主節點:主節點的主要職責是和集群操作相關的內容,如創建或刪除索引,跟蹤哪些節點是群集的一部分,並決定哪些分片分配給相關的節點。穩定的主節點對集群的健康是非常重要的。雖然主節點也可以協調節點,路由搜索和從客戶端新增數據到數據節點,但最好不要使用這些專用的主節點。一個重要的原則是,盡可能做盡量少的工作。
對於大型的生產集群來說,推薦使用一個專門的主節點來控制集群,該節點將不處理任何用戶請求。
數據節點:持有數據和倒排索引。
客戶端節點:它既不能保持數據也不能成為主節點,該節點可以響應用戶的情況,把相關操作發送到其他節點;客戶端節點會將客戶端請求路由到集群中合適的分片上。對於讀請求來說,協調節點每次會選擇不同的分片處理請求,以實現負載均衡。
部落節點:部落節點可以跨越多個集群,它可以接收每個集群的狀態,然後合並成一個全局集群的狀態,它可以讀寫所有節點上的數據。
索引(Index): ES將數據存儲於一個或多個索引中,索引是具有類似特性的文檔的集合。類比傳統的關系型數據庫領域來說,索引相當於SQL中的一個數據庫,或者一個數據存儲方案(schema)。索引由其名稱(必須為全小寫字符)進行標識,並通過引用此名稱完成文檔的創建、搜索、更新及刪除操作。一個ES集群中可以按需創建任意數目的索引。

文檔類型(Type):類型是索引內部的邏輯分區(category/partition),然而其意義完全取決於用戶需求。因此,一個索引內部可定義一個或多個類型(type)。一般來說,類型就是為那些擁有相同的域的文檔做的預定義。例如,在索引中,可以定義一個用於存儲用戶數據的類型,一個存儲日誌數據的類型,以及一個存儲評論數據的類型。類比傳統的關系型數據庫領域來說,類型相當於“表”。

文檔(Document)文檔是Lucene索引和搜索的原子單位,它是包含了一個或多個域的容器,基於JSON格式進行表示。文檔由一個或多個域組成,每個域擁有一個名字及一個或多個值,有多個值的域通常稱為“多值域”。每個文檔可以存儲不同的域集,但同一類型下的文檔至應該有某種程度上的相似之處。相當於數據庫的“記錄”

Mapping: 相當於數據庫中的schema,用來約束字段的類型,不過 Elasticsearch 的 mapping 可以自動根據數據創建
ES中,所有的文檔在存儲之前都要首先進行分析。用戶可根據需要定義如何將文本分割成token、哪些token應該被過濾掉,以及哪些文本需要進行額外處理等等。
分片(shard) :ES的“分片(shard)”機制可將一個索引內部的數據分布地存儲於多個節點,它通過將一個索引切分為多個底層物理的Lucene索引完成索引數據的分割存儲功能,這每一個物理的Lucene索引稱為一個分片(shard)。
每個分片其內部都是一個全功能且獨立的索引,因此可由集群中的任何主機存儲。創建索引時,用戶可指定其分片的數量,默認數量為5個。
Shard有兩種類型:primary和replica,即主shard及副本shard。
Primary shard用於文檔存儲,每個新的索引會自動創建5個Primary shard,當然此數量可在索引創建之前通過配置自行定義,不過,一旦創建完成,其Primary shard的數量將不可更改。
Replica shard是Primary Shard的副本,用於冗余數據及提高搜索性能。
每個Primary shard默認配置了一個Replica shard,但也可以配置多個,且其數量可動態更改。ES會根據需要自動增加或減少這些Replica shard的數量。
ES集群可由多個節點組成,各Shard分布式地存儲於這些節點上。
ES可自動在節點間按需要移動shard,例如增加節點或節點故障時。簡而言之,分片實現了集群的分布式存儲,而副本實現了其分布式處理及冗余功能。

創建索引

技術分享

過程:當分片所在的節點接收到來自協調節點的請求後,會將該請求寫入translog,並將文檔加入內存緩存。如果請求在主分片上成功處理,該請求會並行發送到該分片的副本上。當translog被同步到全部的主分片及其副本上後,客戶端才會收到確認通知。
內存緩沖會被周期性刷新(默認是1秒),內容將被寫到文件系統緩存的一個新段(segment)上。雖然這個段並沒有被同步(fsync),但它是開放的,內容可以被搜索到。
每30分鐘,或者當translog很大的時候,translog會被清空,文件系統緩存會被同步。這個過程在Elasticsearch中稱為沖洗(flush)。在沖洗過程中,內存中的緩沖將被清除,內容被寫入一個新段。段的fsync將創建一個新的提交點,並將內容刷新到磁盤。舊的translog將被刪除並開始一個新的translog。

ES如何做到實時檢索?
由於在buffer中的索引片先同步到文件系統緩存,再刷寫到磁盤,因此在檢索時可以直接檢索文件系統緩存,保證了實時性。
這一步刷到文件系統緩存的步驟,在 Elasticsearch 中,是默認設置為 1 秒間隔的,對於大多數應用來說,幾乎就相當於是實時可搜索了。
不過對於 ELK 的日誌場景來說,並不需要如此高的實時性,而是需要更快的寫入性能。我們可以通過 /_settings接口或者定制 template 的方式,加大 refresh_interval 參數。

當segment從文件系統緩存同步到磁盤時發生了錯誤怎麽辦? 數據會不會丟失

由於Elasticsearch 在把數據寫入到內存 buffer 的同時,其實還另外記錄了一個 translog日誌,如果在這期間故障發生時,Elasticsearch會從commit位置開始,恢復整個translog文件中的記錄,保證數據的一致性。

等到真正把 segment 刷到磁盤,且 commit 文件進行更新的時候, translog 文件才清空。這一步,叫做flush。同樣,Elasticsearch 也提供了 /_flush 接口。

索引數據的一致性通過 translog 保證,那麽 translog 文件自己呢?

Elasticsearch 2.0 以後為了保證不丟失數據,每次 index、bulk、delete、update 完成的時候,一定觸發刷新translog 到磁盤上,才給請求返回 200 OK。這個改變在提高數據安全性的同時當然也降低了一點性能

檢索文檔

技術分享

搜索相關性
相關性是由搜索結果中Elasticsearch打給每個文檔的得分決定的。默認使用的排序算法是tf/idf(詞頻/逆文檔頻率)。詞頻衡量了一個詞項在文檔中出現的次數 (頻率越高 == 相關性越高),逆文檔頻率衡量了詞項在全部索引中出現的頻率,是一個索引中文檔總數的百分比(頻率越高 == 相關性越低)。最後的得分是tf-idf得分與其他因子比如(短語查詢中的)詞項接近度、(模糊查詢中的)詞項相似度等的組合

更新刪除索引

刪除和更新也都是寫操作。但是Elasticsearch中的文檔是不可變的,因此不能被刪除或者改動以展示其變更。那麽,該如何刪除和更新文檔呢?
磁盤上的每個段都有一個相應的.del文件。當刪除請求發送後,文檔並沒有真的被刪除,而是在.del文件中被標記為刪除。該文檔依然能匹配查詢,但是會在結果中被過濾掉。當段合並(我們將在本系列接下來的文章中講到)時,在.del文件中被標記為刪除的文檔將不會被寫入新段。
接下來我們看更新是如何工作的。在新的文檔被創建時,Elasticsearch會為該文檔指定一個版本號。當執行更新時,舊版本的文檔在.del文件中被標記為刪除,新版本的文檔被索引到一個新段。舊版本的文檔依然能匹配查詢,但是會在結果中被過濾掉。
物理刪除索引:當索引數據不斷增長時,對應的segment也會不斷的增多,查詢性能可能就會下降。因此,Elasticsearch會觸發segment合並的線程,把很多小的segment合並成更大的segment,然後刪除小的segment,當這些標記為刪除的segment不會被復制到新的索引段中。

Elasticseach查詢

Elasticseach查詢分為兩種,結構化查詢和全文查詢;
盡管統一稱之為query DSL,事實上Elasticsearch中存在兩種DSL:查詢DSL(query DSL)和過濾DSL(filter DSL)。
查詢子句和過濾子句的自然屬性非常相近,但在使用目的上略有區別。
簡單來講,當執行full-text查詢或查詢結果依賴於相關度分值時應該使用查詢DSL,當執行精確值(extac-value)查詢或查詢結果僅有“yes”或“no”兩種結果時應該使用過濾DSL。
Filter DSL計算及過濾速度較快,且適於緩存,因此可有效提升後續查詢請求的執行速度。
而query DSL不僅要查找匹配的文檔,還需要計算每個文件的相關度分值,因此為更重量級的查詢,其查詢結果不會被緩存。
不過,得益於倒排索引,一個僅返回少量文檔的簡單query或許比一個跨數百萬文檔的filter執行起來並得顯得更慢。
Elasticsearch支持許多的query和filter,但最常用的也不過幾種。
Filter DSL中常見的有term Filter、terms Filter、range Filter、exists and missing Filters和bool Filter。
而Query DSL中常見的有match_all、match 、multi_match及bool Query。鑒於時間關系,這裏不再細述,朋友們可參考官方文檔學習。
Queries用於查詢上下文,而filters用於過濾上下文,不過,Elasticsearch的API也支持此二者合並運行。
組合查詢可用於合並查詢子句,組合過濾用於合並過濾子句,然而,Elasticsearch的使用習慣中,也常會把filter用於query上進行過濾。不過,很少有機會需要把query用於filter上的。

結構化搜索 是指查詢包含內部結構的數據。日期,時間,和數字都是結構化的:它們有明確的格式給你執行邏輯操作。一般包括比較數字或日期的範圍,或確定兩個值哪個大。
文本也可以被結構化。一包蠟筆有不同的顏色:紅色,綠色,藍色。一篇博客可能被打上 分布式 和 搜索的標簽。電子商務產品有商品統一代碼(UPCs) 或其他有著嚴格格式的標識。
通過結構化搜索,你的查詢結果始終是 是或非;是否應該屬於集合。結構化搜索不關心文檔的相關性或分數,它只是簡單的包含或排除文檔。
這必須是有意義的邏輯,一個數字不能比同一個範圍中的其他數字 更多。它只能包含在一個範圍中 —— 或不在其中。類似的,對於結構化文本,一個值必須相等或不等。這裏沒有 更匹配 的概念。

所謂的全文搜索查詢通常是指在給定的文本域內部搜索指定的關鍵字,但搜索操作該需要真正理解查詢者的目的,例如:
(1) 搜索“UK”應該返回包含“United Kingdom”的相關文檔; (2) 搜索“jump”應該返回包含“JUMP”、“jumped”、“jumps”、“jumping”甚至是“leap”的文檔; 為了完成此類全文搜域的搜索,ES必須首先分析文本並將其構建成為倒排索引(inverted index),倒排索引由各文檔中出現的單詞列表組成,列表中的各單詞不能重復且需要指向其所在的各文檔。
因此,為了創建倒排索引,需要先將各文檔中域的值切分為獨立的單詞(也稱為term或token),而後將之創建為一個無重復的有序單詞列表。這個過程稱之為“分詞(tokenization)”。
其次,為了完成此類full-text域的搜索,倒排索引中的數據還需進行“正規化(normalization)”為標準格式,才能評估其與用戶搜索請求字符串的相似度。
這裏的“分詞”及“正規化”操作也稱為“分析(analysis)”。
Analysis過程由兩個步驟的操作組成:首先將文本切分為terms(詞項)以適合構建倒排索引,其次將各terms正規化為標準形式以提升其“可搜索度”。這兩個步驟由分析器(analyzers)完成。
一個分析器通常需要由三個組件構成:字符過濾器(Character filters)、分詞器(Tokenizer)和分詞過濾器(Token filters)組成。
字符過濾器:在文本被切割之前進行清理操作,例如移除HTML標簽,將&替換為字符等;
分詞器:將文本切分為獨立的詞項;簡單的分詞器通常是根據空白及標點符號進行切分;
分詞過濾器:轉換字符(如將大寫轉為小寫)、移除詞項(如移除a、an、of及the等)或者添加詞項(例如,添加同義詞);
Elasticsearch內置了許多字符過濾器、分詞器和分詞過濾器,用戶可按需將它們組合成“自定義”的分析器。

技術分享

與SOLR比對

技術分享

三種使用方式

技術分享技術分享技術分享

使用案例

(1)維基百科,類似百度百科,牙膏,牙膏的維基百科,全文檢索,高亮,搜索推薦

(2)The Guardian(國外新聞網站),類似搜狐新聞,用戶行為日誌(點擊,瀏覽,收藏,評論)+社交網絡
數據(對某某新聞的相關看法),數據分析,給到每篇新聞文章的作者,讓他知道他的文章的公眾反饋(好,
壞,熱門,垃圾,鄙視,崇拜)

(3)Stack Overflow(國外的程序異常討論論壇),IT問題,程序的報錯,提交上去,有人會跟你討論和回答,全文檢索,搜索相關問題和答案,程序報錯了,就會將報錯信息粘貼到裏面去,搜索有沒有對應的答案

(4)GitHub(開源代碼管理),搜索上千億行代碼

(5)電商網站,檢索商品

(6)日誌數據分析,logstash采集日誌,ES進行復雜的數據分析(ELK技術,elasticsearch+logstash+kibana

(7)商品價格監控網站,用戶設定某商品的價格閾值,當低於該閾值的時候,發送通知消息給用戶,比如說訂
閱牙膏的監控,如果高露潔牙膏的家庭套裝低於50塊錢,就通知我,我就去買

(8)BI系統,商業智能,Business Intelligence。比如說有個大型商場集團,BI,分析一下某某區域最近3年

的用戶消費金額的趨勢以及用戶群體的組成構成,產出相關的數張報表,**區,最近3年,每年消費金額呈現
100%的增長,而且用戶群體85%是高級白領,開一個新商場。ES執行數據分析和挖掘,Kibana進行數據可視化
國內
(9)國內:站內搜索(電商,招聘,門戶,等等),IT系統搜索(OA,CRM,ERP,等等),數據分析(ES熱門
的一個使用場景)

elasticsearch學習筆記--原理介紹