日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Elasticsearch如何做到億級數(shù)據(jù)查詢毫秒級返回?

 鷹兔牛熊眼 2019-05-28

如果面試的時候碰到這樣一個面試題:ES 在數(shù)據(jù)量很大的情況下(數(shù)十億級別)如何提高查詢效率?

這個問題說白了,就是看你有沒有實(shí)際用過 ES,因?yàn)樯叮?/span>其實(shí) ES 性能并沒有你想象中那么好的。

很多時候數(shù)據(jù)量大了,特別是有幾億條數(shù)據(jù)的時候,可能你會懵逼的發(fā)現(xiàn),跑個搜索怎么一下 5~10s,坑爹了。

第一次搜索的時候,是 5~10s,后面反而就快了,可能就幾百毫秒。

你就很懵,每個用戶第一次訪問都會比較慢,比較卡么?所以你要是沒玩兒過 ES,或者就是自己玩玩兒 Demo,被問到這個問題容易懵逼,顯示出你對 ES 確實(shí)玩的不怎么樣?

說實(shí)話,ES 性能優(yōu)化是沒有銀彈的。啥意思呢?就是不要期待著隨手調(diào)一個參數(shù),就可以萬能的應(yīng)對所有的性能慢的場景。

也許有的場景是你換個參數(shù),或者調(diào)整一下語法,就可以搞定,但是絕對不是所有場景都可以這樣。

性能優(yōu)化的殺手锏:Filesystem Cache

你往 ES 里寫的數(shù)據(jù),實(shí)際上都寫到磁盤文件里去了,查詢的時候,操作系統(tǒng)會將磁盤文件里的數(shù)據(jù)自動緩存到 Filesystem Cache 里面去。

ES 的搜索引擎嚴(yán)重依賴于底層的 Filesystem Cache,你如果給 Filesystem Cache 更多的內(nèi)存,盡量讓內(nèi)存可以容納所有的 IDX Segment File 索引數(shù)據(jù)文件,那么你搜索的時候就基本都是走內(nèi)存的,性能會非常高。

性能差距究竟可以有多大?我們之前很多的測試和壓測,如果走磁盤一般肯定上秒,搜索性能絕對是秒級別的,1 秒、5 秒、10 秒。

但如果是走 Filesystem Cache,是走純內(nèi)存的,那么一般來說性能比走磁盤要高一個數(shù)量級,基本上就是毫秒級的,從幾毫秒到幾百毫秒不等。

這里有個真實(shí)的案例:某個公司 ES 節(jié)點(diǎn)有 3 臺機(jī)器,每臺機(jī)器看起來內(nèi)存很多 64G,總內(nèi)存就是 64 * 3 = 192G。

每臺機(jī)器給 ES JVM Heap 是 32G,那么剩下來留給 Filesystem Cache 的就是每臺機(jī)器才 32G,總共集群里給 Filesystem Cache 的就是 32 * 3 = 96G 內(nèi)存。

而此時,整個磁盤上索引數(shù)據(jù)文件,在 3 臺機(jī)器上一共占用了 1T 的磁盤容量,ES 數(shù)據(jù)量是 1T,那么每臺機(jī)器的數(shù)據(jù)量是 300G。這樣性能好嗎? 

Filesystem Cache 的內(nèi)存才 100G,十分之一的數(shù)據(jù)可以放內(nèi)存,其他的都在磁盤,然后你執(zhí)行搜索操作,大部分操作都是走磁盤,性能肯定差。

歸根結(jié)底,你要讓 ES 性能好,最佳的情況下,就是你的機(jī)器的內(nèi)存,至少可以容納你的總數(shù)據(jù)量的一半。

根據(jù)我們自己的生產(chǎn)環(huán)境實(shí)踐經(jīng)驗(yàn),最佳的情況下,是僅僅在 ES 中就存少量的數(shù)據(jù),就是你要用來搜索的那些索引,如果內(nèi)存留給 Filesystem Cache 的是 100G,那么你就將索引數(shù)據(jù)控制在 100G 以內(nèi)。

這樣的話,你的數(shù)據(jù)幾乎全部走內(nèi)存來搜索,性能非常之高,一般可以在1秒以內(nèi)。

比如說你現(xiàn)在有一行數(shù)據(jù):id,name,age .... 30 個字段。但是你現(xiàn)在搜索,只需要根據(jù) id,name,age 三個字段來搜索。

如果你傻乎乎往 ES 里寫入一行數(shù)據(jù)所有的字段,就會導(dǎo)致說 90% 的數(shù)據(jù)是不用來搜索的。

結(jié)果硬是占據(jù)了 ES 機(jī)器上的 Filesystem Cache 的空間,單條數(shù)據(jù)的數(shù)據(jù)量越大,就會導(dǎo)致 Filesystem Cahce 能緩存的數(shù)據(jù)就越少。

其實(shí),僅僅寫入 ES 中要用來檢索的少數(shù)幾個字段就可以了,比如說就寫入 es id,name,age 三個字段。

然后你可以把其他的字段數(shù)據(jù)存在 MySQL/HBase 里,我們一般是建議用 ES + HBase 這么一個架構(gòu)。

HBase 的特點(diǎn)是適用于海量數(shù)據(jù)的在線存儲,就是對 HBase 可以寫入海量數(shù)據(jù),但是不要做復(fù)雜的搜索,做很簡單的一些根據(jù) id 或者范圍進(jìn)行查詢的這么一個操作就可以了。

從 ES 中根據(jù) name 和 age 去搜索,拿到的結(jié)果可能就 20 個 doc id,然后根據(jù) doc id 到 HBase 里去查詢每個 doc id 對應(yīng)的完整的數(shù)據(jù),給查出來,再返回給前端。

寫入 ES 的數(shù)據(jù)最好小于等于,或者是略微大于 ES 的 Filesystem Cache 的內(nèi)存容量。

然后你從 ES 檢索可能就花費(fèi) 20ms,然后再根據(jù) ES 返回的 id 去 HBase 里查詢,查 20 條數(shù)據(jù),可能也就耗費(fèi)個 30ms。

可能你原來那么玩兒,1T 數(shù)據(jù)都放 ES,會每次查詢都是 5~10s,現(xiàn)在可能性能就會很高,每次查詢就是 50ms。

數(shù)據(jù)預(yù)熱

假如說,哪怕是你就按照上述的方案去做了,ES 集群中每個機(jī)器寫入的數(shù)據(jù)量還是超過了 Filesystem Cache 一倍。

比如說你寫入一臺機(jī)器 60G 數(shù)據(jù),結(jié)果 Filesystem Cache 就 30G,還是有 30G 數(shù)據(jù)留在了磁盤上。

其實(shí)可以做數(shù)據(jù)預(yù)熱。舉個例子,拿微博來說,你可以把一些大 V,平時看的人很多的數(shù)據(jù),提前在后臺搞個系統(tǒng)。

每隔一會兒,自己的后臺系統(tǒng)去搜索一下熱數(shù)據(jù),刷到 Filesystem Cache 里去,后面用戶實(shí)際上來看這個熱數(shù)據(jù)的時候,他們就是直接從內(nèi)存里搜索了,很快。

或者是電商,你可以將平時查看最多的一些商品,比如說 iPhone 8,熱數(shù)據(jù)提前后臺搞個程序,每隔 1 分鐘自己主動訪問一次,刷到 Filesystem Cache 里去。

對于那些你覺得比較熱的、經(jīng)常會有人訪問的數(shù)據(jù),最好做一個專門的緩存預(yù)熱子系統(tǒng)。

就是對熱數(shù)據(jù)每隔一段時間,就提前訪問一下,讓數(shù)據(jù)進(jìn)入 Filesystem Cache 里面去。這樣下次別人訪問的時候,性能一定會好很多。

冷熱分離

ES 可以做類似于 MySQL 的水平拆分,就是說將大量的訪問很少、頻率很低的數(shù)據(jù),單獨(dú)寫一個索引,然后將訪問很頻繁的熱數(shù)據(jù)單獨(dú)寫一個索引。

最好是將冷數(shù)據(jù)寫入一個索引中,然后熱數(shù)據(jù)寫入另外一個索引中,這樣可以確保熱數(shù)據(jù)在被預(yù)熱之后,盡量都讓他們留在 Filesystem OS Cache 里,別讓冷數(shù)據(jù)給沖刷掉。

你看,假設(shè)你有 6 臺機(jī)器,2 個索引,一個放冷數(shù)據(jù),一個放熱數(shù)據(jù),每個索引 3 個 Shard。3 臺機(jī)器放熱數(shù)據(jù) Index,另外 3 臺機(jī)器放冷數(shù)據(jù) Index。

這樣的話,你大量的時間是在訪問熱數(shù)據(jù) Index,熱數(shù)據(jù)可能就占總數(shù)據(jù)量的 10%,此時數(shù)據(jù)量很少,幾乎全都保留在 Filesystem Cache 里面了,就可以確保熱數(shù)據(jù)的訪問性能是很高的。

但是對于冷數(shù)據(jù)而言,是在別的 Index 里的,跟熱數(shù)據(jù) Index 不在相同的機(jī)器上,大家互相之間都沒什么聯(lián)系了。

如果有人訪問冷數(shù)據(jù),可能大量數(shù)據(jù)是在磁盤上的,此時性能差點(diǎn),就 10% 的人去訪問冷數(shù)據(jù),90% 的人在訪問熱數(shù)據(jù),也無所謂了。

Document 模型設(shè)計

對于 MySQL,我們經(jīng)常有一些復(fù)雜的關(guān)聯(lián)查詢。在 ES 里該怎么玩兒,ES 里面的復(fù)雜的關(guān)聯(lián)查詢盡量別用,一旦用了性能一般都不太好。

最好是先在 Java 系統(tǒng)里就完成關(guān)聯(lián),將關(guān)聯(lián)好的數(shù)據(jù)直接寫入 ES 中。搜索的時候,就不需要利用 ES 的搜索語法來完成 Join 之類的關(guān)聯(lián)搜索了。

Document 模型設(shè)計是非常重要的,很多操作,不要在搜索的時候才想去執(zhí)行各種復(fù)雜的亂七八糟的操作。

ES 能支持的操作就那么多,不要考慮用 ES 做一些它不好操作的事情。如果真的有那種操作,盡量在 Document 模型設(shè)計的時候,寫入的時候就完成。

另外對于一些太復(fù)雜的操作,比如 join/nested/parent-child 搜索都要盡量避免,性能都很差的。

分頁性能優(yōu)化

ES 的分頁是較坑的,為啥呢?舉個例子吧,假如你每頁是 10 條數(shù)據(jù),你現(xiàn)在要查詢第 100 頁,實(shí)際上是會把每個 Shard 上存儲的前 1000 條數(shù)據(jù)都查到一個協(xié)調(diào)節(jié)點(diǎn)上。

如果你有 5 個 Shard,那么就有 5000 條數(shù)據(jù),接著協(xié)調(diào)節(jié)點(diǎn)對這 5000 條數(shù)據(jù)進(jìn)行一些合并、處理,再獲取到最終第 100 頁的 10 條數(shù)據(jù)。

分布式的,你要查第 100 頁的 10 條數(shù)據(jù),不可能說從 5 個 Shard,每個 Shard 就查 2 條數(shù)據(jù),最后到協(xié)調(diào)節(jié)點(diǎn)合并成 10 條數(shù)據(jù)吧?

你必須得從每個 Shard 都查 1000 條數(shù)據(jù)過來,然后根據(jù)你的需求進(jìn)行排序、篩選等等操作,最后再次分頁,拿到里面第 100 頁的數(shù)據(jù)。

你翻頁的時候,翻的越深,每個 Shard 返回的數(shù)據(jù)就越多,而且協(xié)調(diào)節(jié)點(diǎn)處理的時間越長,非??拥K杂?ES 做分頁的時候,你會發(fā)現(xiàn)越翻到后面,就越是慢。

我們之前也是遇到過這個問題,用 ES 作分頁,前幾頁就幾十毫秒,翻到 10 頁或者幾十頁的時候,基本上就要 5~10 秒才能查出來一頁數(shù)據(jù)了。

有什么解決方案嗎?不允許深度分頁(默認(rèn)深度分頁性能很差)。跟產(chǎn)品經(jīng)理說,你系統(tǒng)不允許翻那么深的頁,默認(rèn)翻的越深,性能就越差。

類似于 App 里的推薦商品不斷下拉出來一頁一頁的;類似于微博中,下拉刷微博,刷出來一頁一頁的,你可以用 Scroll API,關(guān)于如何使用,自行上網(wǎng)搜索。

Scroll 會一次性給你生成所有數(shù)據(jù)的一個快照,然后每次滑動向后翻頁就是通過游標(biāo) scroll_id 移動,獲取下一頁、下一頁這樣子,性能會比上面說的那種分頁性能要高很多很多,基本上都是毫秒級的。

但是,唯一的一點(diǎn)就是,這個適合于那種類似微博下拉翻頁的,不能隨意跳到任何一頁的場景。

也就是說,你不能先進(jìn)入第 10 頁,然后去第 120 頁,然后又回到第 58 頁,不能隨意亂跳頁。

所以現(xiàn)在很多產(chǎn)品,都是不允許你隨意翻頁的,App,也有一些網(wǎng)站,做的就是你只能往下拉,一頁一頁的翻。

初始化時必須指定 Scroll 參數(shù),告訴 ES 要保存此次搜索的上下文多長時間。你需要確保用戶不會持續(xù)不斷翻頁翻幾個小時,否則可能因?yàn)槌瑫r而失敗。

除了用 Scroll API,你也可以用 search_after 來做。search_after 的思想是使用前一頁的結(jié)果來幫助檢索下一頁的數(shù)據(jù)。

顯然,這種方式也不允許你隨意翻頁,你只能一頁頁往后翻。初始化時,需要使用一個唯一值的字段作為 Sort 字段。

作者:節(jié)操泛濫的程序員

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多