您好,登錄后才能下訂單哦!
Elasticsearch是一個近實時的分布式搜索分析引擎,常被用作全文搜索,結構化搜索,分析等。它使用 Java 編寫的且開源,它的內部使用 Lucene 做索引與搜索,但是它的目的是使全文檢索變得簡單,通過隱藏 Lucene 的復雜性,取而代之的提供一套簡單一致的 RESTful API。
Lucene 是一個基于Java的全文信息檢索工具庫,它不是一個完整的搜索應用程序,而是為你的應用程序提供索引和搜索功能。Lucene 目前是Apache Jakarta家族中的一個開源項目。也是目前最為流行的基于 Java 開源全文檢索工具庫。
然而,Elasticsearch 不僅僅是 Lucene,并且也不僅僅只是一個全文搜索引擎。 它可以被下面這樣準確的形容:
- 一個分布式的實時文檔存儲,每個字段可以被索引與搜索
- 一個分布式近實時分析搜索引擎
- 能勝任上百個服務節點的擴展,并支持PB級別的結構化或者非結構化數據
cluster集群:一個或多個節點的集合,通過啟動時指定名字作為唯一標識,默認cluster-state
node節點:啟動的ES的單個實例,保存數據并具有索引和搜索的能力,通過名字在集群中唯一標識,默認node-n
index索引:具有相似特點的文檔的集合,可以對應為關系型數據庫中的數據庫,通過名字在集群內唯一標識。可以對應為Mysql中的數據庫。
type文檔類別:索引內部的邏輯分類,ES 6.x 版本中,一個索引只允許一個type,不再支持多個type。7.x版本中,type將廢棄。可以對應為Mysql數據庫中的表。
document文檔:構成索引的最小單元,屬于一個索引的某個類別,通過id 在Type 內唯一標識。可以對應Mysql數據庫的表中的行。
field字段:構成文檔的單元。可以對應Mysql數據庫的表中的列。
mapping索引映射:用來約束文檔字段的類型,可以理解為索引內部結構。可以對應Mysql數據庫的表中每列的類型。
shard分片:將索引分為多個塊,每塊叫做一個分片。索引定義時需要指定分片數且不能更改,默認一個索引有5個分片,每個分片都是一個功能完整的Index,分片帶來規模上(數據水平切分)和性能上(并行執行)的提升,是ES數據存儲的最小單位。
replicas分片的備份:每個分片默認一個備份分片,它可以提升節點的可用性,同時能夠提升搜索時的并發性能(搜索可以在全部分片上并行執行)
索引是現代搜索引擎的核心,建立索引的過程就是把源數據處理成非常方便查詢的索引文件的過程。
為什么索引這么重要呢,試想你現在要在大量的文檔中搜索含有某個關鍵詞的文檔,那么如果不建立索引的話你就需要把這些文檔順序的讀入內存,然后檢查這個文章中是不是含有要查找的關鍵詞,這樣的話就會耗費非常多的時間,想想搜索引擎可是在毫秒級的時間內查找出要搜索的結果的。這就是由于建立了索引的原因,你可以把索引想象成這樣一種數據結構,他能夠使你快速的隨機訪問存儲在索引中的關鍵詞,進而找到該關鍵詞所關聯的文檔。
Lucene 采用的是一種稱為倒排索引(inverted index)的機制。反向索引就是說我們維護了一個詞 / 短語表,對于這個表中的每個詞 / 短語,都有一個鏈表描述了有哪些文檔包含了這個詞 / 短語。這樣在用戶輸入查詢條件的時候,就能非常快的得到搜索結果。我們將在本系列文章的第二部分詳細介紹 Lucene 的索引機制,由于 Lucene 提供了簡單易用的 API,所以即使讀者剛開始對全文本進行索引的機制并不太了解,也可以非常容易的使用 Lucene 對你的文檔實現索引。
對文檔建立好索引后,就可以在這些索引上面進行搜索了。搜索引擎首先會對搜索的關鍵詞進行解析,然后再在建立好的索引上面進行查找,最終返回和用戶輸入的關鍵詞相關聯的文檔。
我們來看下如下 2 個文檔是如何被倒排索引的:
文檔 1(Doc 1): Insight Data Engineering Fellows Program
文檔 2(Doc 2): Insight Data Science Fellows Program
詞項 | 文檔 |
---|---|
data | Doc1,Doc2 |
engineering | Doc1 |
fellows | Doc1,Doc2 |
insight | Doc1,Doc2 |
program | Doc1,Doc2 |
science | Doc2 |
全文檢索首先將要查詢的目標文檔中的詞提取出來,組成索引,通過查詢索引達到搜索目標文檔的目的。這種先建立索引,再對索引進行搜索的過程就叫全文檢索(Full-text Search)。
全文搜索兩個最重要的方面是:
它是評價查詢與其結果間的相關程度,并根據這種相關程度對結果排名的一種能力,這種計算方式可以是 TF/IDF 方法(檢索詞頻率/反向文檔頻率)、地理位置鄰近、模糊相似,或其他的某些算法。
它是將文本塊轉換為有區別的、規范化的token的一個過程,目的是為了創建倒排索引以及查詢倒排索引。
分析主要包含下面的過程:
1,將一塊文本分成適合于倒排索引的獨立的詞條(例如遇見空格和標點來分詞)
2,將這些詞條統一化為標準格式(例如小寫化Quick,刪除詞條像 a,and,the等無用詞,增加詞條像jump和leap這種同義詞等)以提高它們的“可搜索性”
結構化搜索(Structured search)是指有關探詢那些具有內在結構數據的過程。比如日期、時間和數字都是結構化的:它們有精確的格式,我們可以對這些格式進行邏輯操作,例如做大小對比等。
在結構化查詢中,我們得到的結果總是非是即否,要么存于集合之中,要么存在集合之外。結構化查詢不關心文件的相關度或評分;它簡單的對文檔包括或排除處理。
Elasticsearch是面向文檔的,意味著它存儲整個對象或文檔,這里的文檔可以指一個HTML頁面,一封電子郵件,或者是一個文本文件。一個 Document 對象由多個 Field 對象組成的。可以把一個 Document 對象想象成數據庫中的一個記錄,而每個 Field 對象就是記錄的一個字段。Elasticsearch不僅存儲文檔,而且索引每個文檔的內容,使之可以被檢索。在Elasticsearch中,我們對文檔進行索引、檢索、排序和過濾,而不是對行列數據。這是一種完全不同的思考數據的方式,也是 Elasticsearch 能支持復雜全文檢索的原因。
Elasticsearch 使用 JavaScript Object Notation(或者 JSON)作為文檔的序列化格式。JSON 序列化為大多數編程語言所支持,并且已經成為 NoSQL 領域的標準格式。 它簡單、簡潔、易于閱讀。
下面這個 JSON 文檔代表了一個簡單的 user 對象:
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"join_date": "2014/05/01"
}
雖然 Elasticsearch 中的變更不能立即可見,它還是提供了一個近實時的搜索引擎。 Lucene 的變更到磁盤是一個代價昂貴的操作。為了避免在文檔對查詢依然有效的時候,提交變更到磁盤,Elasticsearch 在內存緩沖和磁盤之間提供了一個文件系統緩存。內存緩存 (默認情況下) 每 1 秒刷新一次,在文件系統緩存中使用倒排索引創建一個新的段。這個段是開放的并對搜索有效。
文件系統緩存可以擁有文件句柄,文件可以是開放的、可讀的或者是關閉的,但是它存在于內存之中。因為刷新間隔默認是 1 秒,變更不能立即可見,所以說是近實時的。因為 translog 是尚未落盤的變更持久化記錄,它能有助于 CRUD 操作方面的近實時性。對于每次請求來說,在查找相關段之前,任何最近的變更都能從 translog 搜索到,因此客戶端可以訪問到所有的近實時變更。
你可以在創建 / 更新 / 刪除操作后顯式地刷新索引,使變更立即可見,但我并不推薦你這樣做,因為這樣會創建出來非常多的小 segment 而影響搜索性能。
一個 Elasticsearch實例是一個節點,一組節點組成了集群。Elasticsearch 集群中的節點可以配置為 3 種不同的角色:
主節點:控制 Elasticsearch 集群,負責集群中的操作,比如創建 / 刪除一個索引,跟蹤集群中的節點,分配分片到節點。主節點處理集群的狀態并廣播到其他節點,并接收其他節點的確認響應。每個節點都可以通過設定配置文件elasticsearch.yml中的node.master屬性為true(默認) 成為主節點。對于大型的生產集群來說,推薦使用一個專門的主節點來控制集群,該節點將不處理任何用戶請求。
數據節點:持有數據和倒排索引。默認情況下,每個節點都可以通過設定配置文件elasticsearch.yml中的node.data屬性為true(默認) 成為數據節點。如果我們要使用一個專門的主節點,應將其node.data屬性設置為false。
- 客戶端節點:如果我們將node.master屬性和node.data屬性都設置為false,那么該節點就是一個客戶端節點,扮演一個負載均衡的角色,將到來的請求路由到集群中的各個節點。
green:所有的主分片和副本分片都正常運行。
yellow:所有的主分片都正常運行,但不是所有的副本分片都正常運行。
red:有主分片沒能正常運行。
Elasticsearch使用自己開發的zen discovery算法來選舉集群的master。大概原理如下:
1,對所有可以成為master的節點根據nodeId排序,每次選舉每個節點都把自己所知道節點排一次序,然后選出第一個(第0位)節點,暫且認為它是master節點。
2,如果對某個節點的投票數達到一定的值(可以成為master節點數n/2+1)并且該節點自己也選舉自己,那這個節點就是master。否則重新選舉。
3,對于腦裂問題,需要把候選master節點最小值設置為可以成為master節點數n/2+1(quorum )
當我們發送索引一個新文檔的請求到協調節點后,將發生如下一組操作:
- Elasticsearch集群中的每個節點都包含了改節點上分片的元數據信息。協調節點 (默認)使用文檔ID參與計算,以便為路由提供合適的分片。Elasticsearch使用MurMurHash4函數對文檔ID進行哈希,其結果再對分片數量取模,得到的結果即是索引文檔的分片。
公式:shard = hash(document_id) % (num_of_primary_shards)- 當分片所在的節點接收到來自協調節點的請求后,會將該請求寫入 translog(我們將在本系列接下來的文章中講到),并將文檔加入內存緩沖。如果請求在主分片上成功處理,該請求會并行發送到該分片的副本上。當translog 被同步( fsync ) 到全部的主分片及其副本上后,客戶端才會收到確認通知。
- 內存緩沖會被周期性刷新 (默認是 1 秒),內容將被寫到文件系統緩存的一個新段上。雖然這個段并沒有被同步 (fsync),但它是開放的,內容可以被搜索到。
- 每 30 分鐘,或者當 translog 很大的時候,translog 會被清空,文件系統緩存會被同步。這個過程在 Elasticsearch 中稱為沖洗 (flush)。在沖洗過程中,內存中的緩沖將被清除,內容被寫入一個新段。段的 fsync 將創建一個新的提交點,并將內容刷新到磁盤。舊的 translog 將被刪除并開始一個新的 translog。
刪除和更新也都是寫操作。但是 Elasticsearch 中的文檔是不可變的,因此不能被刪除或者改動以展示其變更。那么,該如何刪除和更新文檔呢?
磁盤上的每個段都有一個相應的.del文件。當刪除請求發送后,文檔并沒有真的被刪除,而是在.del文件中被標記為刪除。該文檔依然能匹配查詢,但是會在結果中被過濾掉。當段合并 (我們將在本系列接下來的文章中講到) 時,在.del文件中被標記為刪除的文檔將不會被寫入新段。
接下來我們看更新是如何工作的。在新的文檔被創建時,Elasticsearch 會為該文檔指定一個版本號。當執行更新時,舊版本的文檔在.del文件中被標記為刪除,新版本的文檔被索引到一個新段。舊版本的文檔依然能匹配查詢,但是會在結果中被過濾掉。
讀操作包含 2 部分內容:
1,查詢階段
2,提取階段
在這個階段,協調節點會將查詢請求路由到索引的全部分片 (主分片或者其副本) 上。每個分片獨立執行查詢,并為查詢結果創建一個優先隊列,以相關性得分排序 (我們將在本系列的后續文章中講到)。全部分片都將匹配文檔的 ID 及其相關性得分返回給協調節點。協調節點創建一個優先隊列并對結果進行全局排序。會有很多文檔匹配結果,但是,默認情況下,每個分片只發送前 10 個結果給協調節點,協調節點為全部分片上的這些結果創建優先隊列并返回前 10 個作為 hit。
當協調節點在生成的全局有序的文檔列表中,為全部結果排好序后,它將向包含原始文檔的分片發起請求。全部分片填充文檔信息并將其返回給協調節點。
master 節點會 ping所有其他節點,以檢查它們是否還活著;然后所有節點 ping 回去,告訴 master 他們還活著。
我們關閉一個主節點Node1。而集群必須擁有一個主節點來保證正常工作,所以發生的第一件事情就是選舉一個新的主節點:Node 2。
在我們關閉 Node 1的同時也失去了主分片1和2,并且在缺失主分片的時候索引也不能正常工作。如果此時來檢查集群的狀況,我們看到的狀態將會為 red :不是所有主分片都在正常工作。我看看到在其它節點上存在著這兩個主分片的完整副本, 所以新的主節點立即將這些分片在 Node 2 和 Node 3 上對應的副本分片提升為主分片, 此時集群的狀態將會為 yellow 。 這個提升主分片的過程是瞬間發生的,如同按下一個開關一般。為什么我們集群狀態是yellow而不是green呢?雖然我們擁有所有的三個主分片,但是同時設置了每個主分片需要對應2份副本分片,而此時只存在一份副本分片。所以集群不能為 green 的狀態。(如果我們設置的副本為1,則集群狀態會變為green)
- 如果我們重新啟動 Node 1 ,集群可以將缺失的副本分片再次進行分配,那么集群的狀態也將完全正常,恢復green狀態。 如果 Node 1 依然擁有著之前的分片,它將嘗試去重用它們,同時僅從主分片復制發生了修改的數據文件。
1,單節點內存不超過32G,使用jvm壓縮指針
2,合理設置索引template,包括settings和mappings
3,使用ssd提升磁盤io
4,數據量大的時候,使用用from,size來深層分頁非常消耗性能,應該禁止使用
5,關閉不使用的索引
6,留一半的系統內存供文件系統緩存使用
7,使用bulk寫入
8,增大實時性要求不高的索引refresh時間
9,關閉系統swap
10,整個集群重啟情況下,延遲分片策略按照需要調整
原因:
1,需要加載所有active狀態index的translog,保證主shard數據完整性主shard恢復之后,rep從主shard復制缺少的部分
2,shard過多
緩解:
1,關閉不需要的索引
2,重啟前flush集群的translog
3,集群恢復的時候,關閉集群寫入,降低集群系統壓力
原因:
1,文件損壞或者文件系統問題
2,機器壓力大導致,allocation分配超時
工具:
1,可以使用explain API具體查看分配失敗的原因
解決:
1,開啟關閉索引,觸發重新分配
2,設置rep為0
3,使用rerouting API,可能有丟數據風險
1,支持類似SQL查詢
2,機器學習
1,默認分片調整為1
2,無type索引結構
3,kibana支持暗黑模式
4,使用Term查詢性能提升3700%
5,對內存管理更加健壯,降低OOM發生
6,時間戳支持納秒級別
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。