Java面試重點(diǎn)中的重點(diǎn)之Elasticsearch核心原理
Elasticsearch簡介
Elasticsearch是什么?它能干什么?
Elasticsearch(以下稱之為ES)是一款基于Lucene的分布式全文搜索引擎,擅長海量數(shù)據(jù)存儲、數(shù)據(jù)分析以及全文檢索查詢,它是一款非常優(yōu)秀的數(shù)據(jù)存儲與數(shù)據(jù)分析中間件,廣泛應(yīng)用于日志分析以及全文檢索等領(lǐng)域,目前很多大廠都基于Elasticsearch開發(fā)了自己的存儲中間件以及數(shù)據(jù)分析平臺。
從核心概念開始
Lucence
Lucene是Apache下的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎,它是ES實現(xiàn)全文檢索的核心基礎(chǔ),索引文檔以及搜索索引的的核心流程都是在Lucene中完成的。
核心數(shù)據(jù)結(jié)構(gòu)
Document
我們都說ES是面向document的,這句話什么意思呢?實際就是表示ES是基于document進(jìn)行數(shù)據(jù)操作的,操作主要包括數(shù)據(jù)搜索以及索引(這里的索引時數(shù)據(jù)寫入的意思)。因此可以說document是ES的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),它會被序列化之后保存到ES中。那么這個document到底是個什么東東呢?相信大家都對Mysql還是比較熟悉的,因此我們用Mysql中的數(shù)據(jù)庫與表的概念與ES的index進(jìn)行對比,可能并不是十分的恰當(dāng)和吻合,但是可以有助于大家對于這些概念的理解。另外type也在ES6.x版本之后逐漸取消了。
Index
在ES之前的版本中,是有type這個概念的,類比數(shù)據(jù)庫中的表,那上文中所說的document就會放在type中。但是在ES后面的版本中為了提高數(shù)據(jù)存儲的效率逐漸取消了type,因此index實際上在現(xiàn)在的ES中既有庫的概念也有表的概念。簡單理解就是index就是文檔的容器,它是一類文檔的集合,但是這里需要注意的是index是邏輯空間的分類,實際數(shù)據(jù)是存在物理空間的分片上的。
另外需要說明的是,在ES中索引是有不同上下文含義的,它既可以是名詞也可以是動詞。索引為名詞是就是上文中提到的它是document的集合,索引為動詞的時候表示將document數(shù)據(jù)保存到ES中,也就是數(shù)據(jù)寫入。
在ES中,為了屏蔽語言的交互差異,ES直接對外的交互都是通過Rest API進(jìn)行的。
倒排索引
我們都知道索引存在的意義就是為了加速數(shù)據(jù)的查詢。在關(guān)系型數(shù)據(jù)庫中如果沒有索引的話,為了查找數(shù)據(jù)我們需要每條數(shù)據(jù)去進(jìn)行比對,運(yùn)氣不好的話可能需要掃描全表才能查找到想要的數(shù)據(jù)。以Mysql為例,它使用了B+樹作為索引來加速數(shù)據(jù)的查詢。假設(shè)有這樣的一種場景,周末在路上逛的時候突然聽到一首非常好聽的歌曲,你記住了其中兩句歌詞,想著趕快拿手機(jī)到QQ音樂中查一下是什么歌。如果你是QQ音樂的程序猿,你該怎么實現(xiàn)根據(jù)歌詞查詢歌曲的功能呢? 用B+樹作為索引行不行呢?全文索引就是需要支持對大文本進(jìn)行索引的,從空間上來說 B+ 樹不適合作為全文索引,同時 B+ 樹因為每次搜索都是從根節(jié)點(diǎn)開始往下搜索,所以會遵循最左匹配原則,而我們使用全文搜索時,往往不會遵循最左匹配原則,所以可能會導(dǎo)致索引失效。這時候倒排索引就派上用場了。 所謂正排索引就像書中的目錄一樣,根據(jù)頁碼查詢內(nèi)容,但是倒排索引確實相反的,它是通過對內(nèi)容的分詞,建立內(nèi)容到文檔ID的關(guān)聯(lián)關(guān)系。這樣在進(jìn)行全文檢索的時候,根據(jù)詞典的內(nèi)容便可以精確以及模糊查詢,非常符合全文檢索的要求。
倒排索引的結(jié)構(gòu)主要包括了兩大部分一個是Term Dictionary(單詞詞典),另一個是Posting List(倒排列表)。Term Dictionary(單詞詞典)記錄了所用文檔的單詞以及單詞和倒排列表的關(guān)系。Posting List(倒排列表)則是記錄了term在文檔中的位置以及其他信息,主要包括文檔ID,詞頻(term在文檔中出現(xiàn)的次數(shù),用來計算相關(guān)性評分),位置以及偏移(實現(xiàn)搜索高亮)。
FST
如上文所述,在進(jìn)行全文檢索的時候,通過倒排索引中term與docId的關(guān)聯(lián)關(guān)系獲取到原始數(shù)據(jù)。但是這里有一個問題,ES底層依賴Lucene實現(xiàn)倒排索引的,因此在進(jìn)行數(shù)據(jù)寫入的時候,Lucene會為原始數(shù)據(jù)中的每個term生成對應(yīng)的倒排索引,因此造成的結(jié)果就是倒排索引的數(shù)據(jù)量就會很大。而倒排索引對應(yīng)的倒排表文件是存儲在硬盤上的。如果每次查詢都直接去磁盤中讀取倒排索引數(shù)據(jù),在通過獲取的docId再去查詢原始數(shù)據(jù)的話,肯定會造成多次的磁盤IO,嚴(yán)重影響全文檢索的效率。因此我們需要一種方式可以快速定位到倒排索引中的term。大家想想使用什么方式比較好呢?可以考慮HashMap, TRIE, Binary Search Tree或者Tenary Search Tree等數(shù)據(jù)結(jié)構(gòu),實際上Lucene實際是使用了FST(Finite State Transducer)有限狀態(tài)傳感器來實現(xiàn)二級索引的設(shè)計,它其實就是一種有限狀態(tài)機(jī)。
我們先來看下 trie樹的結(jié)構(gòu),在Lucene中是這樣做的,將倒排索引中具有公共前綴的term組成一個block,如下圖所示的cool以及copy,它們擁有co的公共前綴,按照類似前綴樹的邏輯來構(gòu)成trie樹,對應(yīng)節(jié)點(diǎn)中攜帶block的首地址。我們來分析下trie樹相比hashmap有什么優(yōu)點(diǎn)?hashmap實現(xiàn)的是精準(zhǔn)查找,但是trie樹不僅可以實現(xiàn)精準(zhǔn)查找,另外由于其公共前綴的特性還可以實現(xiàn)模糊查找。那我們再看trie樹有什么地方可以再進(jìn)行優(yōu)化的地方?
如上如所示,term中的school以及cool的后面字符是一致的,因此我們可以通過將原先的trie樹中的后綴字符進(jìn)行合并來進(jìn)一步的壓縮空間。優(yōu)化后的trie樹就是FST。
因此通過建立FST這個二級索引,可以實現(xiàn)倒排索引的快速定位,不需要經(jīng)過多次的磁盤IO,搜索效率大大提高了。不過需要注意的是FST是存儲在堆內(nèi)存中的,而且是常駐內(nèi)存,大概占用50%-70%的堆內(nèi)存,因此這里也是我們在生產(chǎn)中可以進(jìn)行堆內(nèi)存優(yōu)化的地方。
集群相關(guān)概念
為了增強(qiáng)ES的數(shù)據(jù)存儲可靠性以及高可用,ES支持進(jìn)行集群部署,集群后的ES即便是某些節(jié)點(diǎn)出現(xiàn)故障,也不會導(dǎo)致真?zhèn)€ES集群不可用,同時通過水平擴(kuò)容增強(qiáng)了ES的數(shù)據(jù)存儲能力。
節(jié)點(diǎn)
所謂的節(jié)點(diǎn)實際就是ES的實例,我們通常在一臺服務(wù)器部署一個ES實例,其實就是一個Java進(jìn)程。雖然都是ES實例,但是實際上的ES集群,不同節(jié)點(diǎn)承擔(dān)著不同的能力角色,有的是data node,主要負(fù)責(zé)保存分片的數(shù)據(jù)的,承擔(dān)著數(shù)據(jù)橫向擴(kuò)展的重要作用,有的是coordinating node負(fù)責(zé)將用戶請求進(jìn)行轉(zhuǎn)發(fā)以及將查詢的結(jié)果進(jìn)行合并返回。當(dāng)然還有master節(jié)點(diǎn),負(fù)責(zé)對真?zhèn)€集群狀態(tài)進(jìn)行管理和維護(hù)。
分片
單個ES節(jié)點(diǎn)的數(shù)據(jù)存儲畢竟有限,沒法實現(xiàn)海量數(shù)據(jù)的存儲要求。那么怎么才能滿足海量數(shù)據(jù)的存儲要求呢?一個核心思想就是拆分,比如總共10億條數(shù)據(jù),如果都放在一個節(jié)點(diǎn)中不僅查詢以及數(shù)據(jù)寫入的速度回很慢,頁存在單點(diǎn)問題。在傳統(tǒng)關(guān)系型數(shù)據(jù)庫中,采用分庫分表的方式,用更多的數(shù)據(jù)庫實例來承接大量的數(shù)據(jù)存儲。那么在ES中,也是采取類似的設(shè)計思想,既然一個ES的實例存在數(shù)據(jù)存儲的上線,那么就用多個實例來進(jìn)行存儲。在每個實例中存在的數(shù)據(jù)集合就是分片。如下圖所示,index被切分成三個分片,三個分片分別存儲在三個ES實例中,同時為了提升數(shù)據(jù)的高可用性,每個主分片都有兩個副本分片,這些副本分片是主分片的數(shù)據(jù)拷貝。
put /article { "settings": { "number_of_shards":3, "number_of_replicas":3 } }
這里需要注意的是,分片不是隨意進(jìn)行設(shè)定的,而是需要根據(jù)實際的生產(chǎn)環(huán)境提前進(jìn)行數(shù)據(jù)存儲的容量規(guī)劃,否則分片設(shè)置的過大或者過小都會影響ES集群的整體性能。如果分片設(shè)置的過小,那么單個分片的數(shù)據(jù)量可能會很大,影響數(shù)據(jù)檢索效率,也會影響數(shù)據(jù)的橫向擴(kuò)展。如果分片設(shè)置的過大就會影響搜索結(jié)果的數(shù)據(jù)相關(guān)性評分,影響數(shù)據(jù)檢索的準(zhǔn)確性。
總結(jié)
本文對ES的核心概念進(jìn)行了全面的梳理與闡述,相信大家對于ES有了初步的了解,下篇文章中再帶大家好好理解下ES的核心業(yè)務(wù)流程的原理以及優(yōu)秀的設(shè)計思想,只有理解了ES的核心概念以及核心流程,那么在生產(chǎn)中遇到一些搜索優(yōu)化、節(jié)點(diǎn)JVM優(yōu)化等才會有對應(yīng)的排查方向,另外ES中的一些優(yōu)秀的設(shè)計思想,也是非常值得我們學(xué)習(xí)的,當(dāng)我們在設(shè)計軟件平臺的時候有時可以借鑒這些優(yōu)秀的設(shè)計思想。
到此這篇關(guān)于Java面試重點(diǎn)中的重點(diǎn)之Elasticsearch核心原理的文章就介紹到這了,更多相關(guān)Java Elasticsearch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Spring Data Redis讀不到設(shè)進(jìn)去的值
本文主要介紹了Spring Data Redis怎么讀不到我剛才設(shè)進(jìn)去的值,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Java Swing中的下拉式菜單(menu)、彈出式菜單(JPopupMenu)、選項卡窗體(JTabbedPane)
這篇文章主要介紹了Java Swing中的下拉式菜單(menu)、彈出式菜單(JPopupMenu)、選項卡窗體(JTabbedPane)組件使用案例,需要的朋友可以參考下2014-10-10Java實現(xiàn)4種微信搶紅包算法(小結(jié))
微信紅包是大家經(jīng)常使用的,到現(xiàn)在為止仍然有很多紅包開發(fā)的需求,實現(xiàn)搶紅包算法也是面試??碱},本文就詳細(xì)的來介紹一下如何實現(xiàn),感興趣的可以了解一下2021-12-12SpringBoot+Thymeleaf實現(xiàn)生成PDF文檔
Thymeleaf是一個現(xiàn)代的服務(wù)器端?Java?模板引擎,適用于?Web?和獨(dú)立環(huán)境。Thymeleaf?的主要目標(biāo)是為您的開發(fā)工作流程帶來優(yōu)雅的自然模板,本文就來用它實現(xiàn)生成PDF,感興趣的可以了解一下2022-09-09