在生産環境中, 要保證服務在各種極限情況下的穩定和高可用, 是以在部署ES叢集時, 需要考慮伺服器的記憶體、CPU、磁盤, 叢集的網絡、節點個數, 并且要優化JVM的各項參數. 首先從這些方面着手進行部署前的規劃.
目錄
- 1 伺服器的記憶體
- 2 伺服器的CPU
- 3 伺服器的磁盤
- 4 叢集的網絡
- 5 叢集的節點個數
- 6 JVM的參數設定
- 7 叢集的資料量
- 8 總結
- 版權聲明
ES非常消耗記憶體 —— 不是JVM用到的記憶體, 而是機器的實體記憶體, 因為ES在運作期間對JVM Heap(堆記憶體)的需求較小.
ES底層是基于Lucene建立的, 而Lucene是基于磁盤中的檔案來讀寫和儲存索引資料(包括反向索引、正排索引);
Lucene的特點是基于OS File System Cache(作業系統的檔案緩存系統), 它會盡可能地把頻繁通路的磁盤檔案緩存在作業系統的記憶體中, 進而提高對磁盤檔案的讀寫性能.
關于Lucene的更多資料, 可參考: https://www.cnblogs.com/shoufeng/category/1259723.html.
可以這樣說: ES的性能很大程度上(80%)取決于配置設定給JVM Heap記憶體之後、伺服器的剩餘記憶體大小.
—— 這些剩餘記憶體會緩存Lucene的索引檔案, 緩存的越多, 索引的讀寫性能都越高, 尤其是檢索和聚合操作, 它們需要讀取幾乎所有的索引資料.
實踐建議: 資料量過億, 建議單台伺服器的記憶體至少要有64GB.
ES叢集對CPU的要求比較低, 一般來說2~8個CPU Core即可滿足叢集的需求.
實踐建議: 盡可能使用多核處理器, 因為并發處理能力會更好.
ES生産環境中, 磁盤的讀寫能力是非常重要的, 尤其對于大量寫操作的叢集, 比如電商公司将每天的實時日志資料以高并發的方式寫入ES叢集.
(1) 在磁盤的使用上, 推薦使用SSD(固态硬碟), 而不是(HDD)機械硬碟.
使用SSD, 就需要配置SSD的I/O Scheduler —— 資料寫入磁盤時, IO Scheduler會決定将資料從OS Cache刷入到磁盤的時機.
大部分SSD的預設IO Scheduler是CFQ (completely fair queuing), 它會為每個程序都配置設定一些時間片(time slice), 然後通過磁盤的實體布局來決定如何将資料寫入磁盤 (對各個程序的資料寫入進行優化), 進而提升寫入磁盤的性能.
但是預設的CFQ并不高效. 對SSD來說, 推薦使用Deadline/Noop Scheduler, 它基于寫操作被Pending的時間長短來進行寫磁盤優化, 而Noop Scheduler就是一個簡單的FIFO(先進先出)隊列機制.
(2) 此外, 使用
RAID 0
也是一種提升磁盤讀寫速度的高效方式, 無論是HDD, 或者SSD都支援RAID 0.
RAID 0也被稱之為條帶式(striping)存儲機制, 在RAID各種級别中性能是最高的, 它的基本原理是:
把連續的資料分散存儲到多個磁盤上進行讀寫, 也就是對資料進行條帶式存儲 —— 磁盤的讀寫請求被分散到多個磁盤上并行執行.
沒有必要使用鏡像或者RAID的其他模式, 因為我們并不需要通過RAID來實作資料的高可用存儲 —— 這方面的工作ES的Replica副本機制已經實作了.
(3) 最後, 要避免使用與網絡相關的存儲模式 (network-attached storage, NAS), 比如基于網絡的分布式存儲模式.
雖然很多供應商都說他們的NAS解決方案性能非常高, 而且比本地存儲的可靠性更高, 但在實際使用上還是會有很多風險: 網絡傳輸可能存在比較高的時延, 還可能存在單點故障.
實踐建議: 推薦使用SSD, 并調整其IO Scheduler為Deadline/Noop Scheduler, 這可以帶來很大的性能提升, 理想情況下可能達到上百倍.
對ES這種分布式系統來說, 快速可靠的網絡是非常重要的:
高速網絡通信可以讓ES節點間的通信時延降低;
高帶寬可以讓Shard的移動、恢複, 以及配置設定等操作更加快速.
不低于千兆網卡對大多數叢集來說都已足夠, 但要避免一個叢集橫跨多個資料中心, 比如異地多機房部署一個叢集 —— 跨地域跨機房會降低網絡通信和資料傳輸的效率.
① ES叢集是一種p2p模式的分布式系統架構, 并不是master-slave主從分布式系統.
② ES叢集中, 所有節點都是平等的, 任意兩個節點之間的通信都很頻繁, 如果部署在異地多機房, 就會導緻各個節點之間頻繁跨地域通信, 通信時延會非常高, 甚至有可能造成叢集運作頻繁出現異常.
③ 與NAS存儲模式一樣, 很多供應商都聲稱他們的跨地域多資料中心是可靠、低延遲時間的, 即使果真如此, 一旦網絡出現故障, 整個叢集就會不可用. 大多數情況下, 跨地域多機房部署一個ES叢集帶來的效益要遠遠低于維護這類叢集所付出的額外成本.
實踐建議: 不低于千兆網卡, 且不要垮多個資料中心, 尤其不要跨地域多機房.
ES叢集的節點個數:
① 建議部署少個節點, 但每個節點對應伺服器的資源都必須充足;
② 不建議在一台高性能伺服器上部署多個節點: 不僅降低了叢集的可用性, 而且叢集的維護複雜度也變得更高了.
盡量避免部署大量的低資源的伺服器, 因為對運維和管理而言, 管理5個實體機組成的叢集, 要比管理10個虛拟機組成的叢集要簡單簡單太多.
實踐建議: 小規模、高配置, 但無需超高配置, 會造成資源的浪費.
ES的版本越新, 使用的JDK的版本也應該越新, 既提高性能, 也避免一些不常見的系統Bug(包括Lucene和JDK的).
以本系列博文為例, 示例的ES版本為6.6.0, 使用的JDK版本是
jdk1.8.0_151
.
(1) 如果通過Java API操作ES服務, 那麼編譯Java程式的JVM版本最好與ES伺服器所運作的JVM版本一緻.
ES中用到了很多與JVM版本相關的特性, 比如本地序列化機制 (包括IP位址、異常資訊等等), 而JVM在不同的minor版本中可能會修改序列化機制, 版本不同可能會導緻序列化異常.
(2) 同時官方強烈建議: 不要随意調整JVM的參數設定.
ES是一個非常複雜的分布式軟體系統, 它預設的JVM配置經過了大量真實業務場景下的檢驗, 除非你很明确地知道自己的服務瓶頸出在哪幾個參數上, 否則不要調整.
ES服務中, JVM Heap堆記憶體的大小一般不超過伺服器實體記憶體的一半, 以1/4為宜, 且最多不宜超過32GB.
對很多中小型公司, 建議ES叢集承載的資料量在百億級規模以内.
(1) ES的常見使用場景有:
① 建構業務搜尋功能子產品, 且多是垂直領域的搜尋: 以網站或APP為例, 資料規模相對比較大, 通常是百萬級到億級;
② 進行資料分析: 需要消耗更大的記憶體, 但支援的資料規模要小很多, 通常是十萬級到千萬級;
③ 用于大規模資料的實時OLAP(聯機處理分析), 經典的如ELK Stack, 資料規模可能達到千億或更多, 叢集規模可能達到幾十上百節點.
(2) 資料量特别大時的處理思路:
如果應用的資料量特别大, 日增量幾十上百萬, 那就不建議将資料全量寫入ES中, ES也不适合這種資料無限膨脹的場景 —— ES消耗記憶體, 無限膨脹的資料量會導緻無法提供足夠的記憶體來支撐大規模資料的快速檢索.
此時可以考慮: 将部分熱資料 (比如最近一月的資料) 存放到ES中做高頻高性能搜尋, 将大量的、較少通路的冷資料存放至大資料系統 (比如Hadoop) 中做離線批量處理.
不同資料規模與記憶體容量下的檢索性能表現: 如果伺服器的記憶體可以将ES所需的檔案全部納入到OS Cache中, 就能達到ms(毫秒)級的檢索性能; 否則檢索會大量通路磁盤, 檢索時間就會上升到s(秒)級.
要提升ES的性能, 最重要的是規劃合理的資料量, 配置足夠的實體記憶體用作OS Cache, 盡可能減少從磁盤中通路資料.
作者: 馬瘦風(https://healchow.com)
出處: 部落格園 馬瘦風的部落格(https://www.cnblogs.com/shoufeng)
感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜
本文版權歸部落客所有, 歡迎轉載, 但 [必須在文章頁面明顯位置标明原文連結], 否則部落客保留追究相關人員法律責任的權利.