在生產環境中, 要保證服務在各類極限狀況下的穩定和高可用, 因此在部署ES集羣時, 須要考慮服務器的內存、CPU、磁盤, 集羣的網絡、節點個數, 而且要優化JVM的各項參數. 首先從這些方面着手進行部署前的規劃.html
ES很是消耗內存 —— 不是JVM用到的內存, 而是機器的物理內存, 由於ES在運行期間對JVM Heap(堆內存)的需求較小.java
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)機械硬盤.jvm
使用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://www.cnblogs.com/shoufeng)
感謝閱讀, 若是文章有幫助或啓發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜
本文版權歸博主全部, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文連接], 不然博主保留追究相關人員法律責任的權利.