1. ElasticSearch近實時搜索的實現(xiàn)

        共 3425字,需瀏覽 7分鐘

         ·

        2021-10-16 07:14

        1.近實時搜索

        1.1 實時與近實時

        實時搜索(Real-time Search)很好理解,對于一個數(shù)據(jù)庫系統(tǒng),執(zhí)行插入以后立刻就能搜索到剛剛插入到數(shù)據(jù)。而近實時(Near Real-time),所謂“近”也就是說比實時要慢一點點。

        1.2 近實時的挑戰(zhàn)

        對于一個單機系統(tǒng)來說,這也并不容易實現(xiàn),因為還要保證數(shù)據(jù)的持久化,還要利用緩存等技術(shù)加快數(shù)據(jù)的訪問(注:這里不討論內(nèi)存計算系統(tǒng))。對于ElasticSearch這樣一個分布式系統(tǒng),保證持久化的同時,還要初始化好用于全文檢索的內(nèi)部數(shù)據(jù)結(jié)構(gòu),做到近實時的難度可想而知。而這就是ElasticSearch大獲成功的地方,也正是本文所要學(xué)習(xí)的主題:ElasticSearch是如何解決這些實現(xiàn)近實時搜索的難題的。


        2.ElasticSearch的實現(xiàn)

        2.1 不可變的數(shù)據(jù)結(jié)構(gòu)

        有經(jīng)驗的程序員一定知道,在做并發(fā)編程時,控制可變數(shù)據(jù)的并發(fā)訪問是個難題。古往今來,各種粗細(xì)粒度的鎖,信號量,Actor模型等概念層出不窮。而另一流派函數(shù)式編程更為徹底,尤其是純函數(shù)式比如Haskell,用不可變數(shù)據(jù)來徹底解決這個問題。


        在ElasticSearch這樣主要服務(wù)全文檢索的系統(tǒng)中,Inverted Index是核心數(shù)據(jù)結(jié)構(gòu)。這里簡單說一句,Inverted Index本質(zhì)上一組document中term的各種統(tǒng)計信息,比如最重要的詞頻,以及其他許多統(tǒng)計信息,比如文檔長度,詞序等等。要做到近實時搜索,就要保證新數(shù)據(jù)能快速構(gòu)建,已有數(shù)據(jù)能被高速訪問。解決問題的關(guān)鍵就在于Inverted Index的不可變性,這也是ElasticSearch底層依賴的高性能Lucene的根本奧秘。


        2.2 從不可變到可變

        所以當(dāng)用戶向ElasticSearch中的數(shù)據(jù)庫插入一組document后,底層Lucene構(gòu)建出一個不可變的Inverted Index。可我們知道,一個數(shù)據(jù)庫不可能是靜態(tài)的,當(dāng)用戶再次插入新數(shù)據(jù)時,Lucene該怎樣處理呢?答案就是增量保存和邏輯標(biāo)記。


        所謂增量保存就是為新數(shù)據(jù)構(gòu)建一個新的不可變的Inverted Index,當(dāng)執(zhí)行搜索時,要合并每個Inverted Index中的統(tǒng)計信息得到最終結(jié)果。保存新數(shù)據(jù)的問題解決了,而邏輯標(biāo)記就是解決更新和刪除的。Lucene為每個Inverted Index都額外維護一個del數(shù)據(jù)結(jié)構(gòu),當(dāng)執(zhí)行刪除時,只需在del中標(biāo)記,這樣最終結(jié)果就會排出掉刪除掉document。同理,更新時也是給老數(shù)據(jù)做標(biāo)記,新document會保存在新的Inverted Index中,最終結(jié)果會使用最新版本數(shù)據(jù)的統(tǒng)計信息。在Lucene中,每個Inverted Index叫做Segment,而管理這些Segment的叫做Index。


        ElasticSearch中一個數(shù)據(jù)庫被稱為Index,每個Index可以在創(chuàng)建時指定要劃分為幾份,每一份叫做Shard。Shard會被ElasticSearch分配到不同結(jié)點,運行中還會根據(jù)壓力做Rebalance。這個Shard其實就是Lucene中的Index。由于不同層級上名字的重復(fù),初學(xué)時很容易混淆。


        這種思想其實并非獨創(chuàng),在其他一些高級數(shù)據(jù)結(jié)構(gòu)中也能找到它的影子。如果沒記錯的話,一個經(jīng)典的例子就是LSM樹:https://en.m.wikipedia.org/wiki/Log-structured_merge-tree。


        2.3 分布式數(shù)據(jù)存儲

        對于分布式的數(shù)據(jù)存儲,ElasticSearch采取了經(jīng)典的做法,對數(shù)據(jù)進(jìn)行分片和路由,這里每個分片Shard就是一個Lucene數(shù)據(jù)庫Index。對于有副本replica的Shard,ElasticSearch操作完primary后,再去同步到replica。


        2.4 挑戰(zhàn)磁盤I/O

        現(xiàn)在我們已經(jīng)可以高效地維護全文檢索的數(shù)據(jù)結(jié)構(gòu),也遵循經(jīng)典做法解決了分布式數(shù)據(jù)存儲??删拖袂懊嫣岬降?,還有個挑戰(zhàn)就是磁盤讀寫的巨大開銷。Lucene的做法是,每個Segment在文件系統(tǒng)Cache中構(gòu)建起來就可以被訪問,同步到磁盤的fsync之后才會執(zhí)行。Lucene的Index內(nèi)部的Commit Point會記住哪些Segment還未同步。ElasticSearch默認(rèn)每隔1秒會用Buffer中的document新建一個Segment,這個操作叫做refresh。正因為這1秒鐘的間隔,ElasticSearch支持的是近實時而非實時。


        一個很自然的問題就是每秒鐘都會新建一個Segment,那Lucene Index中的Segment個數(shù)豈不是很容易就爆炸了。每個Segment都是一個物理文件,操作系統(tǒng)中打開文件的句柄個數(shù)是有限的,而且即便不考慮上限,過多Segment也會拖慢搜索,因為前面講過一次搜索的最終結(jié)果是要合并所有Segment中的統(tǒng)計信息的。


        ElasticSearch的做法是維護一個后臺線程去做Merge,Merge的過程中不僅將多個小Segment合并成大的,同時還會排除掉刪除或修改的文件的老版本,最終修改Commit Point排除掉老的Segment,這樣那些“垃圾”document就徹底被刪除了。得益于Segment的不可變性,后臺進(jìn)程Merge時并不會影響數(shù)據(jù)插入和搜索的性能。


        2.5 保證數(shù)據(jù)不丟失

        一個可以預(yù)料到的問題就是,如果當(dāng)前結(jié)點上的ElasticSearch進(jìn)程意外中止,那Buffer中等待處理的document和未同步到磁盤的Segment中的數(shù)據(jù)都會丟失。為了避免這一點,ElasticSearch引入了傳統(tǒng)數(shù)據(jù)庫中所謂的Write-Ahead Log(WAL)日志,ElasticSearch為其起名為translog。每次插入Buffer時,都會同時寫入translog。下面的圖示清晰地展示ElasticSearch是如何與Lucene配合的。


        當(dāng)創(chuàng)建新Segment時,Buffer清空,但translog會一直保留到Segment同步到磁盤才會清空。**所以當(dāng)ElasticSearch重啟時,先根據(jù)Commit Point將所有之前已經(jīng)commit到磁盤的Segment恢復(fù)到Cache,然后再重放(replay)translog中的所有操作。默認(rèn)每30分鐘或者translog很大時,ElasticSearch做一次full commit,即flush操作。


        繼續(xù)刨根問底,translog保證了Buffer和Segment的安全,誰來保證它的安全呢?默認(rèn)情況下,translog每5秒鐘會同步到磁盤,也就是說我們至多會丟失5秒到數(shù)據(jù)。因為translog只是原始的請求document,所以這里的寫磁盤開銷是遠(yuǎn)小于Segment的一次commit的。


        3.題外話:如何深入學(xué)習(xí)ElasticSearch

        以本文為例,談一談如何學(xué)習(xí)ElasticSearch。在有了一些分布式系統(tǒng)和開發(fā)經(jīng)驗后,像本文2.3和2.5節(jié)是完全可以跳過的。前者是分布式系統(tǒng)的通用做法,而后者則早已存在于傳統(tǒng)數(shù)據(jù)庫中。要掌握ElasticSearch,基本用法和系統(tǒng)命令是一方面,而設(shè)計中的精華往往在前文2.1和2.2中。光理解了設(shè)計還不行,就像前面說過的,思想可能流傳已久,但做出來東西的質(zhì)量則可能千差萬別。“天下大事,必做于細(xì)”,實現(xiàn)中的精髓只能在源代碼中體會。


        其實這種方法在另一篇文章里也提到過,就是學(xué)一門編程語言時也是要抓住它的精髓,而不是每門語言都花很多時間去學(xué)基本語法,而沒有精力去掌握精華,最終迷失了。在此再次強調(diào)一下,自己也引以為戒。


        推薦閱讀:

        世界的真實格局分析,地球人類社會底層運行原理

        不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設(shè)PPT)

        企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案

        論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

        企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

        【中臺實踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf

        華為的數(shù)字化轉(zhuǎn)型方法論

        華為如何實施數(shù)字化轉(zhuǎn)型(附PPT)

        超詳細(xì)280頁Docker實戰(zhàn)文檔!開放下載

        華為大數(shù)據(jù)解決方案(PPT)


        瀏覽 36
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 影音先锋成人资源AV在线观看 | 成年视频在线 | 精品码产区一区二视频 | 西西特级444大胆高清张悠雨 | 婷婷激情五月天丁香 |