您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Elasticsearch 的億級數據毫秒級查詢優化思路是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
很多時候數據量大了,特別是有幾億條數據的時候,可能你會懵逼的發現,跑個搜索怎么一下 5~10s,坑爹了。
第一次搜索的時候,是 5~10s,后面反而就快了,可能就幾百毫秒。
你就很懵,每個用戶第一次訪問都會比較慢,比較卡么?所以你要是沒玩兒過 ES,或者就是自己玩玩兒 Demo,被問到這個問題容易懵逼,顯示出你對 ES 確實玩的不怎么樣?
說實話,ES 性能優化是沒有銀彈的。啥意思呢?就是不要期待著隨手調一個參數,就可以萬能的應對所有的性能慢的場景。
也許有的場景是你換個參數,或者調整一下語法,就可以搞定,但是絕對不是所有場景都可以這樣。
你往 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。
假如說,哪怕是你就按照上述的方案去做了,ES 集群中每個機器寫入的數據量還是超過了 Filesystem Cache 一倍。
比如說你寫入一臺機器 60G 數據,結果 Filesystem Cache 就 30G,還是有 30G 數據留在了磁盤上。
其實可以做數據預熱。舉個例子,拿微博來說,你可以把一些大 V,平時看的人很多的數據,提前在后臺搞個系統。
每隔一會兒,自己的后臺系統去搜索一下熱數據,刷到 Filesystem Cache 里去,后面用戶實際上來看這個熱數據的時候,他們就是直接從內存里搜索了,很快。
或者是電商,你可以將平時查看最多的一些商品,比如說 iPhone 8,熱數據提前后臺搞個程序,每隔 1 分鐘自己主動訪問一次,刷到 Filesystem Cache 里去。
對于那些你覺得比較熱的、經常會有人訪問的數據,最好做一個專門的緩存預熱子系統。
就是對熱數據每隔一段時間,就提前訪問一下,讓數據進入 Filesystem Cache 里面去。這樣下次別人訪問的時候,性能一定會好很多。
ES 可以做類似于 MySQL 的水平拆分,就是說將大量的訪問很少、頻率很低的數據,單獨寫一個索引,然后將訪問很頻繁的熱數據單獨寫一個索引。
最好是將冷數據寫入一個索引中,然后熱數據寫入另外一個索引中,這樣可以確保熱數據在被預熱之后,盡量都讓他們留在 Filesystem OS Cache 里,別讓冷數據給沖刷掉。
你看,假設你有 6 臺機器,2 個索引,一個放冷數據,一個放熱數據,每個索引 3 個 Shard。3 臺機器放熱數據 Index,另外 3 臺機器放冷數據 Index。
這樣的話,你大量的時間是在訪問熱數據 Index,熱數據可能就占總數據量的 10%,此時數據量很少,幾乎全都保留在 Filesystem Cache 里面了,就可以確保熱數據的訪問性能是很高的。
但是對于冷數據而言,是在別的 Index 里的,跟熱數據 Index 不在相同的機器上,大家互相之間都沒什么聯系了。
如果有人訪問冷數據,可能大量數據是在磁盤上的,此時性能差點,就 10% 的人去訪問冷數據,90% 的人在訪問熱數據,也無所謂了。
對于 MySQL,我們經常有一些復雜的關聯查詢。在 ES 里該怎么玩兒,ES 里面的復雜的關聯查詢盡量別用,一旦用了性能一般都不太好。
最好是先在 Java 系統里就完成關聯,將關聯好的數據直接寫入 ES 中。搜索的時候,就不需要利用 ES 的搜索語法來完成 Join 之類的關聯搜索了。
Document 模型設計是非常重要的,很多操作,不要在搜索的時候才想去執行各種復雜的亂七八糟的操作。
ES 能支持的操作就那么多,不要考慮用 ES 做一些它不好操作的事情。如果真的有那種操作,盡量在 Document 模型設計的時候,寫入的時候就完成。
另外對于一些太復雜的操作,比如 join/nested/parent-child 搜索都要盡量避免,性能都很差的。
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 頁,不能隨意亂跳頁。
所以現在很多產品,都是不允許你隨意翻頁的,App,也有一些網站,做的就是你只能往下拉,一頁一頁的翻。
初始化時必須指定 Scroll 參數,告訴 ES 要保存此次搜索的上下文多長時間。你需要確保用戶不會持續不斷翻頁翻幾個小時,否則可能因為超時而失敗。
除了用 Scroll API,你也可以用 search_after 來做。search_after 的思想是使用前一頁的結果來幫助檢索下一頁的數據。
顯然,這種方式也不允許你隨意翻頁,你只能一頁頁往后翻。初始化時,需要使用一個唯一值的字段作為 Sort 字段。
以上就是Elasticsearch 的億級數據毫秒級查詢優化思路是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。