成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

ES性能優化原理揭秘!初看一臉懵逼,看懂直接跪下

開發 前端
如果面試的時候碰到這樣一個面試題:ElasticSearch(以下簡稱ES) 在數據量很大的情況下(數十億級別)如何提高查詢效率?

1、一道面試題的引入

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

這個問題說白了,就是看你有沒有實際用過 ES,因為啥?其實 ES 性能并沒有你想象中那么好的。

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

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

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

說實話,ES 性能優化是沒有銀彈的。啥意思呢?就是不要期待著隨手調一個參數,就可以萬能的應對所有的性能慢的場景。

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

2、性能優化的殺手锏:Filesystem Cache

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

整個過程,如下圖所示:

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

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

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

來看一個真實的案例:某個公司 ES 節點有 3 臺機器,每臺機器看起來內存很多 64G,總內存就是 64 * 3 = 192G。

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

而此時,整個磁盤上索引數據文件,在 3 臺機器上一共占用了 1T 的磁盤容量,ES 數據量是 1T,那么每臺機器的數據量是 300G。

這樣性能好嗎?

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

歸根結底,你要讓 ES 性能好,最佳的情況下,就是你的機器的內存,至少可以容納你的總數據量的一半。

根據我們自己的生產環境實踐經驗,最佳的情況下,是僅僅在 ES 中就存少量的數據。

也就是說,你要用來搜索的那些索引,如果內存留給 Filesystem Cache 的是 100G,那么你就將索引數據控制在 100G 以內。這樣的話,你的數據幾乎全部走內存來搜索,性能非常之高,一般可以在1秒以內。

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

如果你傻乎乎往 ES 里寫入一行數據所有的字段,就會導致 90% 的數據是不用來搜索的。

但是呢,這些數據硬是占據了 ES 機器上的 Filesystem Cache 的空間,單條數據的數據量越大,就會導致 Filesystem Cahce 能緩存的數據就越少。

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

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

HBase是列式數據庫,其特點是適用于海量數據的在線存儲,就是對 HBase 可以寫入海量數據,但是不要做復雜的搜索,做很簡單的一些根據 id 或者范圍進行查詢的這么一個操作就可以了。

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

而寫入 ES 的數據最好小于等于,或者是略微大于 ES 的 Filesystem Cache 的內存容量。

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

如果你像原來那么玩兒,1T 數據都放 ES,可能會每次查詢都是 5~10s,而現在性能就會很高,每次查詢就是 50ms。

3、數據預熱

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

比如說你寫入一臺機器 60G 數據,結果 Filesystem Cache 就 30G,還是有 30G 數據留在了磁盤上。

這種情況下,其實可以做數據預熱。舉個例子,拿微博來說,你可以把一些大 V,平時看的人很多的數據,提前在后臺搞個系統。

然后每隔一會兒,自己的后臺系統去搜索一下熱數據,刷到 Filesystem Cache 里去,后面用戶實際上來看這個熱數據的時候,他們就是直接從內存里搜索了,很快。

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

總之,就是對于那些你覺得比較熱的、經常會有人訪問的數據,最好做一個專門的緩存預熱子系統。

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

4、冷熱分離

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

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

還是來一個例子,假設你有 6 臺機器,2 個索引,一個放冷數據,一個放熱數據,每個索引 3 個 Shard。3 臺機器放熱數據 Index,另外 3 臺機器放冷數據 Index。

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

ES 里面的復雜的關聯查詢盡量別用,一旦用了性能一般都不太好。最好是先在 Java 系統里就完成關聯,將關聯好的數據直接寫入 ES 中。搜索的時候,就不需要利用 ES 的搜索語法來完成 Join 之類的關聯搜索了。

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

5、ES中的關聯查詢

對于 MySQL,我們經常有一些復雜的關聯查詢,在 ES 里該怎么玩兒?

ES 里面的復雜的關聯查詢盡量別用,一旦用了性能一般都不太好。最好是先在 Java 系統里就完成關聯,將關聯好的數據直接寫入 ES 中。搜索的時候,就不需要利用 ES 的搜索語法來完成 Join 之類的關聯搜索了。

6、Document 模型設計

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

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

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

7、分頁性能優化

ES 的分頁是較坑的,為啥呢?舉個例子吧,假如你每頁是 10 條數據,你現在要查詢第 100 頁,實際上是會把每個 Shard 上存儲的前 1000 條數據都查到一個協調節點上。

如果你有 5 個 Shard,那么就有 5000 條數據,接著協調節點對這 5000 條數據進行一些合并、處理,再獲取到最終第 100 頁的 10 條數據。

由于是分布式的,你要查第 100 頁的 10 條數據,不可能說從 5 個 Shard,每個 Shard 就查 2 條數據,最后到協調節點合并成 10 條數據吧?

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

你翻頁的時候,翻的越深,每個 Shard 返回的數據就越多,而且協調節點處理的時間越長,非??拥?。所以用 ES 做分頁的時候,你會發現越翻到后面,就越是慢。

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

有什么解決方案嗎?兩個思路:

一、不允許深度分頁(默認深度分頁性能很差)。跟產品經理說,你系統不允許翻那么深的頁,默認翻的越深,性能就越差。

二、類似于 App 里的推薦商品不斷下拉出來一頁一頁的;類似于微博中,下拉刷微博,刷出來一頁一頁的,你可以用 Scroll API,關于如何使用,大家可以自行上網搜索學習一下。

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

但是,唯一的一點就是,這個適合于那種類似微博下拉翻頁的,不能隨意跳到任何一頁的場景。也就是說,你不能先進入第 10 頁,然后去第 120 頁,然后又回到第 58 頁,不能隨意亂跳頁。

所以現在很多產品,都是不允許你隨意翻頁的,你只能往下拉,一頁一頁的翻。

使用時需要注意,初始化必須指定 Scroll 參數,告訴 ES 要保存此次搜索的上下文多長時間。你需要確保用戶不會持續不斷翻頁翻幾個小時,否則可能因為超時而失敗。

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

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

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-09-23 18:16:25

KafkaJVM

2021-11-12 06:39:51

Tomcat連接器面試

2020-12-11 09:20:01

數據庫架構緩存

2020-09-14 12:46:25

過濾器攔截器Filter

2020-11-09 08:51:24

6G衛星

2020-08-25 17:50:36

Redis數據庫內存

2021-02-22 11:13:17

VS Code代碼編程

2021-01-06 10:09:38

MySQL

2020-09-08 06:32:57

項目低耦合高內聚

2020-12-09 09:58:24

緩存策略面試

2023-01-26 02:16:17

2015-08-27 15:54:38

程序員

2015-08-28 09:55:21

程序

2025-04-18 10:17:37

2019-10-30 10:13:15

區塊鏈技術支付寶

2025-02-28 08:21:00

2022-04-15 14:03:09

5G語音通話通信

2025-03-10 08:30:00

2025-05-22 09:43:55

2022-11-21 06:55:08

golang協程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 黄网站在线播放 | 欧美日韩精品久久久免费观看 | av三级 | 手机看片在线播放 | www.日韩高清 | 久久精品国产一区二区电影 | 逼逼网| 欧美日韩国产在线观看 | 久久大全| 精产国产伦理一二三区 | 五十女人一级毛片 | 久热伊人 | 国产视频一视频二 | 久久亚 | 九九精品影院 | 在线观看中文字幕视频 | 精品一区二区三区四区在线 | 99免费看 | 亚洲一二三区精品 | 久久精品一 | 欧美中文字幕一区二区三区亚洲 | 日韩精品福利 | 午夜av电影| 日韩电影免费在线观看中文字幕 | 欧美一区二区三区视频在线观看 | 久久久久久亚洲欧洲 | 大象一区 | 亚洲久久| 国产a区 | 成年人黄色免费视频 | 国产农村妇女毛片精品久久麻豆 | 亚洲午夜在线 | 欧美视频成人 | 欧美精品网 | 欧美一卡二卡在线 | 国产无人区一区二区三区 | 69视频在线播放 | 国产高清一区二区三区 | 久久久国产精品视频 | 欧美一区二区三区在线 | 精品一区二区电影 |