Elasticsearch是什么?它能干什么?
Elasticsearch(以下稱之為ES)是一款基于Lucene的分布式全文搜索引擎,擅長海量資料存盤、資料分析以及全文檢索查詢,它是一款非常優秀的資料存盤與資料分析中間件,廣泛應用于日志分析以及全文檢索等領域,目前很多大廠都基于Elasticsearch開發了自己的存盤中間件以及資料分析平臺,
從核心概念開始
Lucence
Lucene是Apache下的一個子專案,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,它是ES實作全文檢索的核心基礎,索引檔案以及搜索索引的的核心流程都是在Lucene中完成的,

核心資料結構
Document
我們都說ES是面向document的,這句話什么意思呢?實際就是表示ES是基于document進行資料操作的,操作主要包括資料搜索以及索引(這里的索引時資料寫入的意思),因此可以說document是ES的基礎資料結構,它會被序列化之后保存到ES中,那么這個document到底是個什么東東呢?相信大家都對Mysql還是比較熟悉的,因此我們用Mysql中的資料庫與表的概念與ES的index進行對比,可能并不是十分的恰當和吻合,但是可以有助于大家對于這些概念的理解,另外type也在ES6.x版本之后逐漸取消了,

Index
在ES之前的版本中,是有type這個概念的,類比資料庫中的表,那上文中所說的document就會放在type中,但是在ES后面的版本中為了提高資料存盤的效率逐漸取消了type,因此index實際上在現在的ES中既有庫的概念也有表的概念,簡單理解就是index就是檔案的容器,它是一類檔案的集合,但是這里需要注意的是index是邏輯空間的分類,實際資料是存在物理空間的分片上的,

另外需要說明的是,在ES中索引是有不同背景關系含義的,它既可以是名詞也可以是動詞,索引為名詞是就是上文中提到的它是document的集合,索引為動詞的時候表示將document資料保存到ES中,也就是資料寫入,

在ES中,為了屏蔽語言的互動差異,ES直接對外的互動都是通過Rest API進行的,
倒排索引
我們都知道索引存在的意義就是為了加速資料的查詢,在關系型資料庫中如果沒有索引的話,為了查找資料我們需要每條資料去進行比對,運氣不好的話可能需要掃描全表才能查找到想要的資料,以Mysql為例,它使用了B+樹作為索引來加速資料的查詢,假設有這樣的一種場景,周末在路上逛的時候突然聽到一首非常好聽的歌曲,你記住了其中兩句歌詞,想著趕快拿手機到QQ音樂中查一下是什么歌,如果你是QQ音樂的程式猿,你該怎么實作根據歌詞查詢歌曲的功能呢?
用B+樹作為索引行不行呢?全文索引就是需要支持對大文本進行索引的,從空間上來說 B+ 樹不適合作為全文索引,同時 B+ 樹因為每次搜索都是從根節點開始往下搜索,所以會遵循最左匹配原則,而我們使用全文搜索時,往往不會遵循最左匹配原則,所以可能會導致索引失效,這時候倒排索引就派上用場了,
所謂正排索引就像書中的目錄一樣,根據頁碼查詢內容,但是倒排索引確實相反的,它是通過對內容的分詞,建立內容到檔案ID的關聯關系,這樣在進行全文檢索的時候,根據詞典的內容便可以精確以及模糊查詢,非常符合全文檢索的要求,

倒排索引的結構主要包括了兩大部分一個是Term Dictionary(單詞詞典),另一個是Posting List(倒排串列),Term Dictionary(單詞詞典)記錄了所用檔案的單詞以及單詞和倒排串列的關系,Posting List(倒排串列)則是記錄了term在檔案中的位置以及其他資訊,主要包括檔案ID,詞頻(term在檔案中出現的次數,用來計算相關性評分),位置以及偏移(實作搜索高亮),

FST
如上文所述,在進行全文檢索的時候,通過倒排索引中term與docId的關聯關系獲取到原始資料,但是這里有一個問題,ES底層依賴Lucene實作倒排索引的,因此在進行資料寫入的時候,Lucene會為原始資料中的每個term生成對應的倒排索引,因此造成的結果就是倒排索引的資料量就會很大,而倒排索引對應的倒排表檔案是存盤在硬碟上的,如果每次查詢都直接去磁盤中讀取倒排索引資料,在通過獲取的docId再去查詢原始資料的話,肯定會造成多次的磁盤IO,嚴重影響全文檢索的效率,因此我們需要一種方式可以快速定位到倒排索引中的term,大家想想使用什么方式比較好呢?可以考慮HashMap, TRIE, Binary Search Tree或者Tenary Search Tree等資料結構,實際上Lucene實際是使用了FST(Finite State Transducer)有限狀態傳感器來實作二級索引的設計,它其實就是一種有限狀態機,
我們先來看下 trie樹的結構,在Lucene中是這樣做的,將倒排索引中具有公共前綴的term組成一個block,如下圖所示的cool以及copy,它們擁有co的公共前綴,按照類似前綴樹的邏輯來構成trie樹,對應節點中攜帶block的首地址,我們來分析下trie樹相比hashmap有什么優點?hashmap實作的是精準查找,但是trie樹不僅可以實作精準查找,另外由于其公共前綴的特性還可以實作模糊查找,那我們再看trie樹有什么地方可以再進行優化的地方?

如上如所示,term中的school以及cool的后面字符是一致的,因此我們可以通過將原先的trie樹中的后綴字符進行合并來進一步的壓縮空間,優化后的trie樹就是FST,

因此通過建立FST這個二級索引,可以實作倒排索引的快速定位,不需要經過多次的磁盤IO,搜索效率大大提高了,不過需要注意的是FST是存盤在堆記憶體中的,而且是常駐記憶體,大概占用50%-70%的堆記憶體,因此這里也是我們在生產中可以進行堆記憶體優化的地方,

集群相關概念
為了增強ES的資料存盤可靠性以及高可用,ES支持進行集群部署,集群后的ES即便是某些節點出現故障,也不會導致真個ES集群不可用,同時通過水平擴容增強了ES的資料存盤能力,
節點
所謂的節點實際就是ES的實體,我們通常在一臺服務器部署一個ES實體,其實就是一個Java行程,雖然都是ES實體,但是實際上的ES集群,不同節點承擔著不同的能力角色,有的是data node,主要負責保存分片的資料的,承擔著資料橫向擴展的重要作用,有的是coordinating node負責將用戶請求進行轉發以及將查詢的結果進行合并回傳,當然還有master節點,負責對真個集群狀態進行管理和維護,

分片
單個ES節點的資料存盤畢竟有限,沒法實作海量資料的存盤要求,那么怎么才能滿足海量資料的存盤要求呢?一個核心思想就是拆分,比如總共10億條資料,如果都放在一個節點中不僅查詢以及資料寫入的速度回很慢,頁存在單點問題,在傳統關系型資料庫中,采用分庫分表的方式,用更多的資料庫實體來承接大量的資料存盤,那么在ES中,也是采取類似的設計思想,既然一個ES的實體存在資料存盤的上線,那么就用多個實體來進行存盤,在每個實體中存在的資料集合就是分片,如下圖所示,index被切分成三個分片,三個分片分別存盤在三個ES實體中,同時為了提升資料的高可用性,每個主分片都有兩個副本分片,這些副本分片是主分片的資料拷貝,
put /article
{
"settings": {
"number_of_shards":3,
"number_of_replicas":3
}
}

這里需要注意的是,分片不是隨意進行設定的,而是需要根據實際的生產環境提前進行資料存盤的容量規劃,否則分片設定的過大或者過小都會影響ES集群的整體性能,如果分片設定的過小,那么單個分片的資料量可能會很大,影響資料檢索效率,也會影響資料的橫向擴展,如果分片設定的過大就會影響搜索結果的資料相關性評分,影響資料檢索的準確性,
總結
本文對ES的核心概念進行了全面的梳理與闡述,相信大家對于ES有了初步的了解,下篇文章中再帶大家好好理解下ES的核心業務流程的原理以及優秀的設計思想,只有理解了ES的核心概念以及核心流程,那么在生產中遇到一些搜索優化、節點JVM優化等才會有對應的排查方向,另外ES中的一些優秀的設計思想,也是非常值得我們學習的,當我們在設計軟體平臺的時候有時可以借鑒這些優秀的設計思想,
大家好,我是慕楓,感謝各位小伙伴點贊、收藏和評論,文章持續更新,我們下期再見!
微信搜索:慕楓技術筆記,優質文章持續更新,我們有學習打卡的群可以拉你進,一起努力沖擊大廠,另外有很多學習以及面試的材料提供給大家,
真正的大師永遠懷著一顆學徒的心

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/394202.html
標籤:其他
上一篇:使用 Spark GraphX 實作 PageRank 演算法
下一篇:最新批量搜狗域名添加系結工具
