共計 4529 個字符,預計需要花費 12 分鐘才能閱讀完成。
這篇文章將為大家詳細講解有關怎么解析大規模 Elasticsearch 集群管理,文章內容質量較高,因此丸趣 TV 小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
ElasticSearch 目前在互聯網公司主要用于兩種應用場景,其一是用于構建業務的搜索功能模塊且多是垂直領域的搜索,數據量級一般在千萬至數十億這個級別; 其二用于大規模數據的實時 OLAP,經典的如 ELKStack,數據規模可能達到千億或更多。 這兩種場景的數據索引和應用訪問模式上差異較大,在硬件選型和集群優化方面側重點也會有所不同。一般來說后一種場景屬于大數據范疇,數據量級和集群規模更大,在管理方面也更有挑戰。
目前我們最大的日志單集群有 120 個 data node,運行于 70 臺物理服務器上。數據規模如下:
單日索引數據條數 600 億,新增索引文件 25TB (含一個復制片則為 50TB)
業務高峰期峰值索引速率維持在百萬條 / 秒
歷史數據保留時長根據業務需求制定,從 10 天 ndash; 90 天不等
集群共 3441 個索引、17000 個分片、數據總量約 9300 億, 磁盤總消耗 1PB
Kibana 用戶 600 多人, 每日來自 Kibana 和第三方的 API 調用共 63 萬次
查詢響應時間百分位 75%:0.160s 90%:1.640s 95%:6.691s 99%:14.0039s
運維這樣大規模的 ES 集群,有哪些值得注意的地方?
一. 必不可少的工具
工欲善其事必先利其器,從一開始,哪怕就只有幾個 node,就應該使用分布式配置管理工具來做集群的部署。隨著應用的成熟,集群規模的逐步擴大,效率的提升會凸顯。 官方提供了 ES Puppet Module 和 Chef Cookbook,熟悉這兩個工具的同學可以直接拿過來用。 我們自己則是采用的 Ansible,編寫了一套 Playbook 來達到類似的效果。 用熟這類工具,對于集群的初始部署,配置批量更改,集群版本升級,重啟故障結點都會快捷和安全許多。
第二個必備利器就是 sense 插件。通過這個插件直接調用集群的 restful API,在做集群和索引的狀態查看,索引配置更改的時候非常方便。語法提示和自動補全功能更是實用,減少了翻看文檔的頻率。在 Kibana5 里面,sense 已經成為一個內置的控制臺,無需額外安裝。
二. 硬件配置
我們采用的是 32vcoreCPU + 128GB RAM 的服務器,磁盤配置大部分服務器是 12 塊 4TB SATA 機械磁盤做的 Raid0,少部分機器是剛上了不久的 6 塊 800GB SSD raid0,主要目的是想做冷熱數據分離,后面談到集群架構的時候,再進一步解釋一下如何利用硬件資源。
三. 集群的管理
首先很有必要對 ES 的結點做角色劃分和隔離。大家知道 ES 的 data node 除了放數據以外,也可以兼任 master 和 client 的角色,多數同學會將這些角色混入到 data node。然而對于一個規模較大,用戶較多的集群,master 和 client 在一些極端使用情況下可能會有性能瓶頸甚至內存溢出,從而使得共存的 data node 故障。data node 的故障恢復涉及到數據的遷移,對集群資源有一定消耗,容易造成數據寫入延遲或者查詢減慢。如果將 master 和 client 獨立出來,一旦出現問題,重啟后幾乎是瞬間就恢復的,對用戶幾乎沒有任何影響。另外將這些角色獨立出來的以后,也將對應的計算資源消耗從 data node 剝離出來,更容易掌握 data node 資源消耗與寫入量和查詢量之間的聯系,便于做容量管理和規劃。
避免過高的并發,包括控制 shard 數量和 threadpool 的數量。在寫入量和查詢性能能夠滿足的前提下,為索引分配盡量少的分片。分片過多會帶來諸多負面影響,例如:每次查詢后需要匯總排序的數據更多; 過多的并發帶來的線程切換造成過多的 CPU 損耗; 索引的刪除和配置更新更慢 Issue#18776; 過多的 shard 也帶來更多小的 segment,而過多的小 segment 會帶來非常顯著的 heap 內存消耗,特別是如果查詢線程配置得很多的情況下。 配置過大的 threadpool 更是會產生很多詭異的性能問題 Issue#18161 里所描述的問題就是我們所經歷過的。 默認的 Theadpool 大小一般來說工作得很不錯了。
冷熱數據最好做分離。對于日志型應用來說,一般是每天建立一個新索引,當天的熱索引在寫入的同時也會有較多的查詢。如果上面還存有比較長時間之前的冷數據,那么當用戶做大跨度的歷史數據查詢的時候,過多的磁盤 IO 和 CPU 消耗很容易拖慢寫入,造成數據的延遲。所以我們用了一部分機器來做冷數據的存儲,利用 ES 可以給結點配置自定義屬性的功能,為冷結點加上”boxtype”:”weak”的標識,每晚通過維護腳本更新冷數據的索引路由設置 index.routing.allocation.{require|include|exclude},讓數據自動向冷結點遷移。 冷數據的特性是不再寫入,用戶查的頻率較低,但量級可能很大。比如我們有個索引每天 2TB,并且用戶要求保持過去 90 天數據隨時可查。保持這么大量的索引為 open 狀態,并非只消耗磁盤空間。ES 為了快速訪問磁盤上的索引文件,需要在內存里駐留一些數據(索引文件的索引),也就是所謂的 segment memory。稍微熟悉 ES 的同學知道,JVM heap 分配不能超過 32GB,對于我們 128GB RAM, 48TB 磁盤空間的機器而言,如果只跑一個 ES 實例,只能利用到 32GB 不到的 heap,當 heap 快用飽和的時候,磁盤上保存的索引文件還不到 10TB,這樣顯然是不經濟的。 因此我們決定在冷結點上跑 3 個 ES 實例,每個分配 31GB heap 空間,從而可以在一臺物理服務器上存儲 30 多 TB 的索引數據并保持 open 狀態,供用戶隨時搜索。 實際使用下來,由于冷數據搜索頻率不高,也沒有寫入,即時只剩余 35GB 內存給 os 做文件系統緩存,查詢性能還是可以滿足需求的。
不同數據量級的 shard 最好隔離到不同組別的結點。 大家知道 ES 會自己平衡 shard 在集群的分布,這個自動平衡的邏輯主要考量三個因素。其一同一索引下的 shard 盡量分散到不同的結點; 其二每個結點上的 shard 數量盡量接近; 其三結點的磁盤有足夠的剩余空間。這個策略只能保證 shard 數量分布均勻,而并不能保證數據大小分布均勻。 實際應用中,我們有 200 多種索引,數據量級差別很大,大的一天幾個 TB,小的一個月才幾個 GB,并且每種類型的數據保留時長又千差萬別。拋出的問題,就是如何能比較平衡并充分的利用所有節點的資源。 針對這個問題,我們還是通過對結點添加屬性標簽來做分組,結合 index routing 控制的方式來做一些精細化的控制。盡量讓不同量級的數據使用不同組別的結點,使得每個組內結點上的數據量比較容易自動平衡。
定期做索引的 force merge,并且最好是每個 shard merge 成一個 segment。前面提到過,heap 消耗與 segment 數量也有關系,force merge 可以顯著降低這種消耗。 如果 merge 成一個 segment 還有一個好處,就是對于 terms aggregation,搜索時無需構造 Global Ordinals,可以提升聚合速度。
四. 版本選擇
我們在 2.4 版本上穩定跑了很長時間,比較保守的同學可以上 2.4,激進有精力折騰的可以考慮最新的 5.0。 我們集群兩周前從 v2.4.0 升級到了 v5.0.0 這個版本,除了升級第一周遇到一個不穩定的問題以外,感覺新版本帶來的以下特性還是非常值得去升級的:
結點啟動的 Bootstrap 過程加入了很多關鍵系統參數設置的核驗,比如 Max File Descriptors, Memory Lock, Virtual Memory 設置等等,如果設置不正確會拒絕啟動并拋出異常。與其帶著錯誤的系統參數啟動,并在日后造成性能問題,不如啟動失敗告知用戶問題,是個很好的設計!
索引性能提升。升級后在同樣索引速率下,我們看到 cpu 消耗下降非常明顯,除了對索引速率提升有幫助,也會一定程度提升搜索速率。
新的數值型數據結構,存儲空間更小,Range 和地理位置計算更快速
Instant Aggregation 對于類似 now-7d to now 這樣的范圍查詢聚合能夠做 cache 了,實際使用下來,效果明顯,用戶在 Kibana 上跑個過去一周數據的聚合,頭 2 次刷新慢點,之后有 cache 了幾乎就瞬間刷出!
更多的保護措施保證集群的穩定,比如對一次搜索 hit 的 shard 數量做了限制,增強了 circuit breaker 的特性,更好的防護集群資源被壞查詢耗盡。
升級第一周,我們的冷數據結點出現間歇性不響應問題,從而刨出 3 個 issue 提交給官方:
Issue#21595 Issue#21612 Issue#21611
第一個問題確認為 Bug,將在 5.0.2 修復,其他兩個目前還不清楚根源,看起來也只在我們的應用場景里遇到了。所幸問題都找到了了規避措施,實施這些措施以后,最近一周我們的集群重新回到以前 2.4 版本時期的穩定狀態。
五. 監控
不差錢沒空折騰的建議還是買官方的 xpack 省心,有精力折騰的,利用 ES 各種豐富的 stats api,用自己熟悉的監控工具采集數據,可視化出來就好了。 那么多監控指標,最最關鍵的還是以下幾類:
各類 Thread pool 的使用情況,active/queue/reject 可視化出來。 判斷集群是否有性能瓶頸了,看看業務高峰期各類 queue 是不是很高,reject 是不是經常發生,基本可以做到心里有數。
JVM 的 heap used% 以及 old GC 的頻率,如果 old GC 頻率很高,并且多次 GC 過后 heap used% 幾乎下不來,說明 heap 壓力太大,要考慮擴容了。(也有可能是有問題的查詢或者聚合造成的,需要結合用戶訪問記錄來判斷)。
Segment memory 大小和 Segment 的數量。節點上存放的索引較多的時候,這兩個指標就值得關注,要知道 segment memory 是常駐 heap 不會被 GC 回收的,因此當 heap 壓力太大的時候,可以結合這個指標判斷是否是因為節點上存放的數據過多,需要擴容。Segement 的數量也是比較關鍵的,如果小的 segment 非常多,比如有幾千,即使 segment memory 本身不多,但是在搜索線程很多的情況下,依然會吃掉相當多的 heap,原因是 lucene 為每個 segment 會在 thread local 里記錄狀態信息,這塊的 heap 內存開銷和 (segment 數量 * thread 數量) 相關。
很有必要記錄用戶的訪問記錄。我們只開放了 http api 給用戶,前置了一個 nginx 做 http 代理,將用戶第三方 api 的訪問記錄通過 access log 全部記錄下來。通過分析訪問記錄,可以在集群出現性能問題時,快速找到問題根源,對于問題排查和性能優化都很有幫助。
關于怎么解析大規模 Elasticsearch 集群管理就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。