前面介紹了ElasticSearch原理和使用相關(guān)的內容,在生產(chǎn)環(huán)境如何比較科學(xué)的進(jìn)行容量規劃、部署、調優(yōu)、排查問(wèn)題呢,業(yè)界和官方也對相關(guān)的問(wèn)題進(jìn)行總結,我這邊也結合自己的經(jīng)驗對這些使用ElasticSearch經(jīng)常遇到的問(wèn)題進(jìn)行了總結。其中主要包括以下三大模塊:
部署模式
容量規劃與調優(yōu)
問(wèn)題診斷
2.1. 節點(diǎn)類(lèi)型
2.1.1. 節點(diǎn)分類(lèi)
ElasticSearch有多種類(lèi)型的節點(diǎn),在前面概述和核心也已經(jīng)介紹過(guò)了。在這里可以重新回顧下。ElasticSearch的部署節點(diǎn)類(lèi)型如下:
Master eligible
主節點(diǎn)及其候選節點(diǎn),負責集群狀態(tài)(cluster state)的管理
配置項:node.master,默認為true
data
數據節點(diǎn),負責數據存儲及處理客戶(hù)端請求
配置項:node.data,默認為true
Ingest
ingest節點(diǎn),負責數據處理,腳本執行
配置項:node.ingest,默認為true
Coordinating
協(xié)調節點(diǎn)
配置項:設置上面三個(gè)參數全部為false,那么它就是一個(gè)純協(xié)調節點(diǎn)
machine learning
機器學(xué)習節點(diǎn),收費屬于x-pack
2.1.2 節點(diǎn)推薦配置
在生產(chǎn)環(huán)境部署推薦配置整體思路就是:盡量是一個(gè)節點(diǎn)只承擔一個(gè)角色。
因為不同的節點(diǎn)所需要的計算機資源都不一樣。職責分離后可以按需擴展互不影響。
Master
資源要求:中高CPU;中高內存;中低磁盤(pán)
一般在生產(chǎn)環(huán)境中配置3臺
一個(gè)集群只有1臺活躍的主節點(diǎn),負責分片管理,索引創(chuàng )建,集群管理等操作
data
資源要求:CPU、內存、磁盤(pán)要求都高
ingest
資源要求:高配置CPU;中等配置的RAM;低配置的磁盤(pán)
Coordinating
資源要求:一般中高CPU;中高內存;低磁盤(pán)
協(xié)調節點(diǎn)扮演者負載均衡、結果的聚合,在大型的es集群中條件允許可以使用高配的cpu和內存。因為如果客戶(hù)端發(fā)起了深度分頁(yè)等請求可能會(huì )導致oom,這個(gè)在之前也有過(guò)分析。
注意:
如果和數據節點(diǎn)或者Coordinate節點(diǎn)混合部署,數據節點(diǎn)本來(lái)相對有比較大的內存占用。
而Coordinate節點(diǎn)有時(shí)候可能會(huì )有開(kāi)銷(xiāo)很高的查詢(xún)導致OOM,這些甚至都有可能影響Master節點(diǎn),導致集群的不穩定。
2.2. 架構模式
搭建一個(gè)es集群是由模式可循的。
2.2.1 基礎版部署

這是一個(gè)基礎版的職責分離的部署架構:
比如當磁盤(pán)容量無(wú)法滿(mǎn)足需求時(shí),可以增加數據節點(diǎn);
磁盤(pán)讀寫(xiě)壓力大時(shí),增加數據節點(diǎn)。
但是如果大量的聚合查詢(xún)等操作,這種架構不太適合了。
2.2.2 水平擴展部署

當系統中有大量的復雜查詢(xún)或者聚合時(shí)候,我們可增加Coordinating節點(diǎn),增加查詢(xún)的性能,這里增加了負載均衡層,通過(guò)負載均衡擴展時(shí)應用程序無(wú)感知。
2.2.3 讀寫(xiě)分離

這樣部署部署相互影響,寫(xiě)入多的話(huà),多部署ingetst節點(diǎn),讀的時(shí)候聚合查詢(xún)較多可以多部署協(xié)調節點(diǎn),存儲數據量大,可以適當對數據節點(diǎn)進(jìn)行調優(yōu)。
2.2.4 冷熱分離
我們知道數據有冷熱之分,比如寫(xiě)入頻繁的日志數據,近期的索引將會(huì )頻繁寫(xiě)入。es根據數據這些特征引入了hot節點(diǎn)和warm節點(diǎn)。
hot節點(diǎn)
使用ssd,該節點(diǎn)上的索引不斷的有新文檔寫(xiě)入和查詢(xún),對cpu、io的要求較高。
warm節點(diǎn)
可以使用HDD,上面的索引不會(huì )有寫(xiě)入,查詢(xún)較少。上面只保存只讀索引或者舊索引,使用大容量便宜的機械硬盤(pán)。

配置步驟:
在ElasticSearch節點(diǎn)啟動(dòng)的時(shí)候,在ElasticSearch.yml配置文件node.attr中指定當前的節點(diǎn)是hot還是warm。如:
node.attr.testNodeType=hot
通過(guò)GET/_cat/nodeattrs?v查看所有的節點(diǎn)的狀態(tài)

創(chuàng )建索引時(shí)指定在何種類(lèi)型的節點(diǎn)上,使用屬性:
'index.routing.allocation.require.testNodeType':'hot'
也可以在已有的索引上使用上述屬性,它會(huì )將索引的數據遷移到hot節點(diǎn)上
2.2.5 異地多活
針對多機房災備,ElasticSearch業(yè)界有多種不同的通用解決方案:
跨機房部署集群
一個(gè)集群中的節點(diǎn)分布在不同的機房
優(yōu)點(diǎn):部署簡(jiǎn)單,一致性高。
缺點(diǎn):但是對網(wǎng)絡(luò )帶寬和延遲要求較高,僅適用于同城災備,可能導致可能由于機房間網(wǎng)絡(luò )中斷造成不可用。
應用雙寫(xiě)
應用程序同時(shí)將數據寫(xiě)入兩個(gè)集群
優(yōu)點(diǎn):應用端靈活可控
缺點(diǎn):但是一致性差、延遲高、集群故障時(shí)數據會(huì )丟失
借助消息隊列實(shí)現雙寫(xiě)
應用程序先將數據寫(xiě)入消息隊列,然后由下游的消費者消費并寫(xiě)入集群
優(yōu)點(diǎn):這種方案數據可靠性高,不易丟失
缺點(diǎn):引入額外的消息隊列組件,維護成本高,開(kāi)發(fā)難度大、延遲高,需要保證消息中間件的高可用。
CCR跨集群復制
ElasticSearch官方的跨集群復制功能,基于文檔操作實(shí)現訂閱復制
優(yōu)點(diǎn):一致性高、設置簡(jiǎn)單、延遲低、提供完善的API,并且可以監控同步進(jìn)度,整體有保障。
缺點(diǎn):白金功能,會(huì )員獨享;集群之間拉取數據可能會(huì )增加額外的負載并影響原有集群本身的磁盤(pán)和網(wǎng)絡(luò )性能
定期快照
定期將索引備份到外部存儲,如hdfs等設備
優(yōu)點(diǎn):操作簡(jiǎn)單,無(wú)技術(shù)成本
缺點(diǎn):但是需要通過(guò)快照將數據恢復到新集群中,恢復時(shí)間長(cháng),數據不是實(shí)時(shí)備份,可能丟失數據
極限網(wǎng)關(guān)
寫(xiě)請求交給網(wǎng)關(guān),網(wǎng)關(guān)實(shí)時(shí)寫(xiě)入主集群,然后異步寫(xiě)備集群
優(yōu)點(diǎn):無(wú)縫透明,應用程序無(wú)需任何調整、網(wǎng)關(guān)自動(dòng)處理故障情況、一致性高,通過(guò)校驗任務(wù)確保數據完全一致
對網(wǎng)關(guān)的要求較高
如下是基于CCR跨集群復制的部署架構,因為篇幅有限,異地多活又是一個(gè)很大的話(huà)題,其它方案和其細節可以查閱相關(guān)資料。

3.1. 分片
我們知道當es集群的節點(diǎn)數大于索引的分片數時(shí),集群將無(wú)法通過(guò)水平擴展提升集群的性能。而分片數過(guò)多,對于聚合查詢(xún)以及集群的元數據管理也都有影響。我們可以總結為:
分片數量較多
優(yōu)點(diǎn):
新數據節點(diǎn)加入后,分片會(huì )自動(dòng)分配擴展性強
數據寫(xiě)入分散到不同節點(diǎn),減少每個(gè)節點(diǎn)的壓力
缺點(diǎn):
每個(gè)分片就是一個(gè)lucene索引,這個(gè)索引會(huì )占用較多的機器資源,造成額外的開(kāi)銷(xiāo)
搜索時(shí),需要到每個(gè)分片獲取數據
master節點(diǎn)維護分片、索引的元信息,造成master節點(diǎn)管理成本過(guò)高。
通常建議一個(gè)集群總分片數小于10w。
如何設計分片的數量呢?一個(gè)分片保持多大的數據量比較合適呢?
3.1.1 主分片
我們需要根據使用場(chǎng)景來(lái)設置:
日志類(lèi),其特點(diǎn)為:寫(xiě)入頻繁,查詢(xún)較少
單個(gè)分片不要大于50G
搜索類(lèi),其特點(diǎn)為:寫(xiě)入較少,查詢(xún)頻繁
單個(gè)分片不超過(guò)20G
避免使用非常大的分片,因為這會(huì )對群集從故障中恢復的能力產(chǎn)生負面影響。而每個(gè)分片也會(huì )消耗相應的文件句柄,內存和CPU資源,分片太多會(huì )互相競爭,影響性能。
主分片數一旦確定就無(wú)法更改,只能新建創(chuàng )建并對數據進(jìn)行重新索引(reindex),雖然reindex會(huì )比較耗時(shí),但至少能保證你不會(huì )停機。所以我們一定要科學(xué)的設計分片數。
這里摘錄于官方關(guān)于分片大小的建議:
小的分片會(huì )造成小的分段,從而會(huì )增加開(kāi)銷(xiāo)。我們的目的是將平均分片大小控制在幾 GB 到幾十 GB 之間。對于基于時(shí)間的數據的使用場(chǎng)景來(lái)說(shuō),通常將分片大小控制在 20GB 到 40GB 之間。
由于每個(gè)分片的開(kāi)銷(xiāo)取決于分段的數量和大小,因此通過(guò) forcemerge 操作強制將較小的分段合并為較大的分段,這樣可以減少開(kāi)銷(xiāo)并提高查詢(xún)性能。 理想情況下,一旦不再向索引寫(xiě)入數據,就應該這樣做。 請注意,這是一項比較耗費性能和開(kāi)銷(xiāo)的操作,因此應該在非高峰時(shí)段執行。
我們可以在節點(diǎn)上保留的分片數量與可用的堆內存成正比,但 ElasticSearch沒(méi)有強制的固定限制。 一個(gè)好的經(jīng)驗法則是確保每個(gè)節點(diǎn)的分片數量低于每GB堆內存配置20到25個(gè)分片。 因此,具有30GB堆內存的節點(diǎn)應該具有最多600-750個(gè)分片,但是低于該限制可以使其保持更好。 這通常有助于集群保持健康。
如果擔心數據的快速增長(cháng), 建議根據這條限制: ?ElasticSearch推薦的最大JVM堆空間 是 30~32G, 所以把分片最大容量限制為 30GB, 然后再對分片數量做合理估算。例如, 如果的數據能達到 200GB, 則最多分配7到8個(gè)分片。
如果是基于日期的索引需求, 并且對索引數據的搜索場(chǎng)景非常少。
也許這些索引量將達到成百上千, 但每個(gè)索引的數據量只有1GB甚至更小對于這種類(lèi)似場(chǎng)景, 建議是只需要為索引分配1個(gè)分片。如果使用ES7的默認配置(3個(gè)分片), 并且使用 Logstash 按天生成索引, 那么 6 個(gè)月下來(lái), 擁有的分片數將達到 540個(gè). 再多的話(huà), 你的集群將難以工作--除非提供了更多(例如15個(gè)或更多)的節點(diǎn)。想一下, 大部分的 Logstash 用戶(hù)并不會(huì )頻繁的進(jìn)行搜索, 甚至每分鐘都不會(huì )有一次查詢(xún). 所以這種場(chǎng)景, 推薦更為經(jīng)濟使用的設置. 在這種場(chǎng)景下, 搜索性能并不是第一要素, 所以并不需要很多副本。
維護單個(gè)副本用于數據冗余已經(jīng)足夠。不過(guò)數據被不斷載入到內存的比例相應也會(huì )變高。如果索引只需要一個(gè)分片, 那么使用 Logstash 的配置可以在 3 節點(diǎn)的集群中維持運行 6 個(gè)月。當然你至少需要使用 4GB 的內存, 不過(guò)建議使用 8GB, 因為在多數據云平臺中使用 8GB 內存會(huì )有明顯的網(wǎng)速以及更少的資源共享。
3.1.2. 副本分片
主分片與副本都能處理查詢(xún)請求,它們的唯一區別在于只有主分片才能處理索引請求。副本對搜索性能非常重要,同時(shí)用戶(hù)也可在任何時(shí)候添加或刪除副本。額外的副本能給帶來(lái)更大的容量,更高的呑吐能力及更強的故障恢復能力
3.1.3. 小結
根據實(shí)際經(jīng)驗我們稍微總結下:
對于數據量較?。?00GB以下)的index
往往寫(xiě)入壓力查詢(xún)壓力相對較低,一般設置3~5個(gè)shard,numberofreplicas設置為1即可(也就是一主一從,共兩副本)。
對于數據量較大(100GB以上)的index:
一般把單個(gè)shard的數據量控制在(20GB~50GB)
讓index壓力分攤至多個(gè)節點(diǎn):可通過(guò)下面的參數來(lái)強制限定一個(gè)節點(diǎn)上該index的shard數量,讓shard盡量分配到不同節點(diǎn)上。參數:
index.routing.allocation.totalshardsper_node
綜合考慮整個(gè)index的shard數量,如果shard數量(不包括副本)超過(guò)50個(gè),就很可能引發(fā)拒絕率上升的問(wèn)題,此時(shí)可考慮把該index拆分為多個(gè)獨立的index,分攤數據量,同時(shí)配合routing使用,降低每個(gè)查詢(xún)需要訪(fǎng)問(wèn)的shard數量。
3.2. 集群配置
3.2.1 jvm配置
xms和xmx設置成一樣,避免heap resize時(shí)卡頓
xmx不要超過(guò)物理內存的50%
因為es的lucene寫(xiě)入強依賴(lài)于操作系統緩存,需要預留加多的空間給操作系統
最大內存不超過(guò)32G,但是也不要太小
堆太小會(huì )導致頻繁的小延遲峰值,并因不斷的垃圾收集暫停而降低吞吐量;
如果堆太大,應用程序將容易出現來(lái)自全堆垃圾回收的罕見(jiàn)長(cháng)延遲峰值;
將堆限制為略小于32GB可以使用jvm的指針壓縮技術(shù)增強性能;
jvm使用server模式
推薦采用g1垃圾回收器
關(guān)閉jvm swapping
關(guān)閉交換分區的方法是:
//將/etc/fstab 文件中包含swap的行注釋掉sed -i '/swap/s/^/#/' /etc/fstabswapoff -a其它的配置盡量不要修改,使用默認的配置。
適當增大寫(xiě)入buffer和bulk隊列長(cháng)度,提高寫(xiě)入性能和穩定性
indices.memory.index_buffer_size: 15%thread_pool.bulk.queue_size: 1024這里是官方的jvm推薦配置鏈接:
https://www.elastic.co/cn/blog/a-heap-of-trouble
3.2.2 集群節點(diǎn)數
es的節點(diǎn)提供查詢(xún)的時(shí)候使用較多的內存來(lái)存儲查詢(xún)緩存,es的lucene寫(xiě)入到磁盤(pán)也會(huì )先緩存在內存中,我們開(kāi)啟設計這個(gè)es節點(diǎn)時(shí)需要根據每個(gè)節點(diǎn)的存儲數據量來(lái)進(jìn)行判斷。這里有一個(gè)流行的推薦比例配置:
搜索類(lèi)比例:1:16(內存:節點(diǎn)要存儲的數據)
日志類(lèi)比例:1:48-1:96(內存:節點(diǎn)要存儲的數據)
示例:
有一個(gè)業(yè)務(wù)的數據量預估實(shí)際有1T,我們把副本設置1個(gè),那么es中總數據量為2T。
如果業(yè)務(wù)偏向于搜索
每個(gè)節點(diǎn)31*16=496G。在加上其它的預留空間,每個(gè)節點(diǎn)有400G的存儲空間。2T/400G,則需要5個(gè)es存儲節點(diǎn)。
如果業(yè)務(wù)偏向于寫(xiě)入日志型
每個(gè)節點(diǎn)31*50=1550G,就只需要2個(gè)節點(diǎn)即可
這里31G表示的是jvm設置不超過(guò)32g否則不會(huì )使用java的指針壓縮優(yōu)化了。
3.2.3 網(wǎng)絡(luò )優(yōu)化
單個(gè)集群不要跨機房部署
如果有多塊網(wǎng)卡,可以將tranport和http綁定到不同的網(wǎng)卡上,可以起到隔離的作用
使用負載聚合到協(xié)調節點(diǎn)和ingest node節點(diǎn)
3.2.4 磁盤(pán)優(yōu)化
前面也提到過(guò),數據節點(diǎn)推薦使用ssd
3.2.5 通用設置
關(guān)閉動(dòng)態(tài)索引創(chuàng )建功能
通過(guò)模板設置白名單
3.2.6 其它優(yōu)化
Linux參數調優(yōu)修改系統資源限制#單用戶(hù)可以打開(kāi)的最大文件數量,可以設置為官方推薦的65536或更大些echo
設置內存熔斷參數,防止寫(xiě)入或查詢(xún)壓力過(guò)高導致OOM
indices.breaker.total.limitindices.breaker.request.limitindices.breaker.fielddata.limit索引、分片等信息都被維護在clusterstate對象中,由master管理,并分發(fā)給各個(gè)節點(diǎn)。當集群中的index/shard過(guò)多,創(chuàng )建索引等基礎操作會(huì )變成越來(lái)越慢,而且master節點(diǎn)的不穩定會(huì )影響整體集群的可用性。
可以考慮:
拆分獨立獨有的master節點(diǎn)
降低數據量較小的index的shard數量
把一些有關(guān)聯(lián)的index合并成一個(gè)index
數據按某個(gè)維度做拆分,寫(xiě)入多個(gè)集群
3.3 寫(xiě)入和查詢(xún)優(yōu)化
3.3.1 寫(xiě)入優(yōu)化
寫(xiě)入的目標在于增大寫(xiě)入的吞吐量,這里主要從兩個(gè)方面進(jìn)行優(yōu)化:
客戶(hù)端:
通過(guò)壓測確定每次寫(xiě)入的文檔數量。一般情況:
單個(gè)bulk請求數據兩不要太大,官方建議5-15mb
寫(xiě)入請求超時(shí)時(shí)間建議60s以上
寫(xiě)入盡量不要一直寫(xiě)入同一節點(diǎn),輪詢(xún)達到不同節點(diǎn)。
進(jìn)行多線(xiàn)程寫(xiě)入,最好的情況時(shí)動(dòng)態(tài)調整,如果http429,此時(shí)可以少寫(xiě)入點(diǎn),不是可以多寫(xiě)點(diǎn)
寫(xiě)入數據不指定_id,讓ES自動(dòng)產(chǎn)生
當用戶(hù)顯示指定id寫(xiě)入數據時(shí),ES會(huì )先發(fā)起查詢(xún)來(lái)確定index中是否已經(jīng)有相同id的doc存在,若有則先刪除原有doc再寫(xiě)入新doc。
這樣每次寫(xiě)入時(shí),ES都會(huì )耗費一定的資源做查詢(xún)。
如果用戶(hù)寫(xiě)入數據時(shí)不指定doc,ES則通過(guò)內部算法產(chǎn)生一個(gè)隨機的id,并且保證id的唯一性,這樣就可以跳過(guò)前面查詢(xún)id的步驟,提高寫(xiě)入效率。
server:
總體目標盡可能壓榨服務(wù)器資源,提高吞吐量
使用好的硬件,觀(guān)察cpu、ioblock、內存是否有瓶頸。
觀(guān)察jvm堆棧,垃圾回收情況是否存在耗時(shí)較長(cháng)的gc。
觀(guān)察寫(xiě)入的分配和節點(diǎn)是否負載均衡。
調整bulk線(xiàn)程池和隊列的大小,一般不用調整,它是根據現有核數和內存自動(dòng)算出來(lái)的,酌情調整。一般線(xiàn)程數配置為CPU核心數+1,隊列也不要太大,否則gc比較頻繁。
可靠性要求不高,可以副本設置為0。
磁盤(pán)io肯定沒(méi)有內存快,可以在允許的情況refresh調整間隔大一點(diǎn)。
flush閾值適當調大、落盤(pán)異步化、flush頻率調高。這些都能減少寫(xiě)入資源的占用,提升寫(xiě)入吞吐能力。但是對容災能力有損害。
索引設置優(yōu)化。
減少不必要的分詞,從而降低cpu和磁盤(pán)的開(kāi)銷(xiāo)。
只需要聚合不需要搜索,index設置成false不需要算分,可以將norms設置成false
不要對字符串使用默認的dynmic mapping。會(huì )自動(dòng)分詞產(chǎn)生不必要的開(kāi)銷(xiāo)。
index_options控制在創(chuàng )建倒排索引時(shí),哪些內容會(huì )被條件到倒排索引中,只添加有用的,這樣能很大減少cpu的開(kāi)銷(xiāo)。
關(guān)閉_source,減少io操作。但是source字段用來(lái)存儲文檔的原始信息,如果我們以后可能reindex,那就必須要有這個(gè)字段。
設置30s refresh,降低lucene生成頻次,資源占用降低提升寫(xiě)入性能,但是損耗實(shí)時(shí)性。
total_shards_per_node控制分片集中到某一節點(diǎn),避免熱點(diǎn)問(wèn)題。
translong落盤(pán)異步化,提升性能,損耗災備能力。
dynamic設置false,避免生成多余的分詞字段,需要自行確定映射。
merge并發(fā)控制。
ES的一個(gè)index由多個(gè)shard組成,而一個(gè)shard其實(shí)就是一個(gè)Lucene的index,它又由多個(gè)segment組成,且Lucene會(huì )不斷地把一些小的segment合并成一個(gè)大的segment,這個(gè)過(guò)程被稱(chēng)為merge。
我們可以通過(guò)調整并發(fā)度來(lái)減少這一步占用的資源操作。
index.merge.scheduler.max_thread_count這里可以針對myindex索引優(yōu)化的示例:
PUT myindex { 'settings': { 'index' :{ 'refresh_interval' : '30s','number_of_shards' :'2' }, 'routing': { 'allocation': { 'total_shards_per_node' :'3' } }, 'translog' :{ 'sync_interval' : '30s', 'durability' : 'async' }, number_of_replicas' : 0 } 'mappings': { 'dynamic' : false, 'properties' :{} }}3.3.2 查詢(xún)優(yōu)化
首先有幾個(gè)原則我們需要清楚:
ElasticSearch不是關(guān)系型數據庫,即使ElasticSearch支持嵌套、父子查詢(xún),但是會(huì )嚴重損耗ElasticSearch的性能,速度也很慢。
盡量先將數據計算出來(lái)放到索引字段中,不要查詢(xún)的時(shí)候再通過(guò)es的腳本來(lái)進(jìn)行計算。
盡量利用filter的緩存來(lái)查詢(xún)

設計上不要深度分頁(yè)查詢(xún),否則可能會(huì )使得jvm內存爆滿(mǎn)。
可以通過(guò)profile、explain工具來(lái)分析慢查詢(xún)的原因。
嚴禁*號通配符為開(kāi)頭的關(guān)鍵字查詢(xún),我們可以利用不同的分詞器進(jìn)行模糊查詢(xún)。
分片數優(yōu)化,避免每次查詢(xún)訪(fǎng)問(wèn)每一個(gè)分片,可以借助路由字段進(jìn)行查詢(xún)。
需要控制單個(gè)分片的大?。?/span>
這個(gè)上面有提到:查詢(xún)類(lèi):20GB以?xún)?;日志?lèi):50G以?xún)取?/span>
讀但是不寫(xiě)入文檔的索引進(jìn)行lucene段進(jìn)行強制合并。
優(yōu)化數據模型、數據規模、查詢(xún)語(yǔ)句。
4.1 索引健康狀態(tài)
4.1.1 監控狀態(tài)
綠色代表集群的索引的所有分片(主分片和副本分片)正常分配了。
紅色代表至少一個(gè)主分片沒(méi)有分配。
黃色代表至少一個(gè)副本沒(méi)有分配。
我們可以通過(guò)health相關(guān)的api進(jìn)行查看
//集群的狀態(tài)(檢查節點(diǎn)數量)GET _cluster/health//所有索引的健康狀態(tài) (查看有問(wèn)題的索引)GET _cluster/health?level=indices//單個(gè)索引的健康狀態(tài)(查看具體的索引)GET _cluster/health/my_index//分片級的索引GET_cluster/health?level=shards//返回第一個(gè)未分配Shard 的原因GET _cluster/allocation/explain
4.1.2 常見(jiàn)原因
集群變紅。
創(chuàng )建索引失敗,我們可以通過(guò)Allocation Explain API查看,會(huì )返回解釋信息。
集群重啟階段,短暫變紅。
打開(kāi)一個(gè)之前關(guān)閉的索引。
有節點(diǎn)離線(xiàn)。通常只需要重啟離線(xiàn)的節點(diǎn)使其回來(lái)即可。
一個(gè)節點(diǎn)離開(kāi)集群,有索引被刪除,離開(kāi)的節點(diǎn)又回來(lái)了。會(huì )導致出現紅色,產(chǎn)生了dangling索引。
磁盤(pán)空間限制,分片規則(Shard Filtering)引發(fā)的,需要調整規則或者增加節點(diǎn)。官方文檔給出了詳細的未分配分片的可能原因:
https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-shards.html
集群變黃。
無(wú)法創(chuàng )建副本,因為副本能和它的主分配在一個(gè)節點(diǎn)上,可能副本數過(guò)大或者節點(diǎn)數過(guò)少導致。
4.2. 慢查詢(xún)
4.2.1 profile api
我們可以使用profile api來(lái)定位慢查詢(xún)。
在查詢(xún)條件中設置profile為true的參數,將會(huì )顯示查詢(xún)經(jīng)歷的細節。
GET trace_segment_record_202204291430/_search{ 'query': { 'match': { 'serviceIp' : 'xxxxx' } }, 'profile': true}其結果為:

這里會(huì )返回一個(gè)shards列表。其中:
id
【nodeId】【shardId】
query
主要包含了如下信息:
query_type
展示了哪種類(lèi)型的查詢(xún)被觸發(fā)。
lucene
顯示啟動(dòng)的lucene方法
time
執行lucene查詢(xún)小號的時(shí)間
breakdown
里面包含了lucene查詢(xún)的一些細節參數
rewrite_time
多個(gè)關(guān)鍵字會(huì )分解創(chuàng )建個(gè)別查詢(xún),這個(gè)分解過(guò)程花費的時(shí)間。將重寫(xiě)一個(gè)或者多個(gè)組合查詢(xún)的時(shí)間被稱(chēng)為”重寫(xiě)時(shí)間“
collector
在Lucene中,收集器負責收集原始結果,并對它們進(jìn)行組合、過(guò)濾、排序等處理。這里我們可以根據這個(gè)查看收集器里面花費的時(shí)間及一些參數。
Profile API讓我們清楚地看到查詢(xún)耗時(shí)。提供了有關(guān)子查詢(xún)的詳細信息,我們可以清楚地知道在哪個(gè)環(huán)節查詢(xún)慢,另外返回的結果中,關(guān)于Lucene的詳細信息也讓我們深入了解到ES是如何執行查詢(xún)的。
4.2.2 查看慢日志
ES記錄了兩類(lèi)慢日志:
慢搜索日志
用來(lái)記錄哪些查詢(xún)比較慢,每個(gè)節點(diǎn)可以設置不同的閾值。
之前我們已經(jīng)詳細分析了ES的搜索由兩個(gè)階段組成:
查詢(xún)
取回
慢搜索日志給出了每個(gè)階段所花費的時(shí)間和整個(gè)查詢(xún)內容本身。慢搜索日志可以為查詢(xún)和取回階段單獨設置以時(shí)間為單位的閾值,在定義好每個(gè)級別的時(shí)間后,通過(guò)level決定輸出哪個(gè)級別的日志。
示例如下
PUT kibana_sample_data_logs/_settings{'index.search.slowlog.threshold.query.warn': '100ms','index.search.slowlog.threshold.query.info': '50ms','index.search.slowlog.threshold.query.debug': '10ms','index.search.slowlog.threshold.query.trace': '60ms','index.search.slowlog.threshold.fetch.warn': '100ms','index.search.slowlog.threshold.fetch.info': '50ms','index.search.slowlog.threshold.fetch.debug': '20ms','index.search.slowlog.threshold.fetch.trace': '60ms','index.search.slowlog.level': 'debug'}
[2030-08-30T11:59:37,786][WARN ][i.s.s.query] [node-0] [index6][0] took[78.4micros], took_millis[0], total_hits[0 hits], stats[], search_type[QUERY_THEN_FETCH], total_shards[1], source[{'query':{'match_all':{'boost':1.0}}}], id[MY_USER_ID],前面參考官方鏈接:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index-modules-slowlog.html
4.3 節點(diǎn)異常
4.3.1 節點(diǎn)cpu過(guò)高
如果出現節點(diǎn)占用CPU很高,我們需要知道CPU在運行什么任務(wù),一般通過(guò)線(xiàn)程堆棧來(lái)查看。
這里有兩種方式可以查看哪些線(xiàn)程CPU占用率比較高:
使用ElasticSearch提供的hot_threads api查看;
使用jstack和top命令查看,針對java應用cpu過(guò)高問(wèn)題的這個(gè)是通用做法。
這里推薦使用hot_threads api
GET /_nodes/hot_threadsGET /_nodes/<node_id>/hot_threads
通過(guò)返回的結果可以看到什么線(xiàn)程占用更高,正在做什么操作。更詳細的內容可以參考官網(wǎng):
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-nodes-hot-threads.html
4.3.2 內存使用率過(guò)高
1)緩存類(lèi)型
首先我們需要了解ES中的緩存類(lèi)型,緩存主要分成如圖所示三大類(lèi),如下圖所示,一個(gè)es節點(diǎn)的內存結構:

Node Query Cache(Filter Context)
每一個(gè)節點(diǎn)有一個(gè)Node Query緩存
由該節點(diǎn)的所有Shard共享,只緩存Filter Context 相關(guān)內容
Cache采用LRU算法,不會(huì )被jvm gc
Segment級緩存命中的結果。Segment被合并后,緩存會(huì )失效
緩存的配置項設置為
index.queries.cache.enabled: trueindices.queries.cache.size:10%Shard Query Cache(Cache Query的結果)
緩存每個(gè)分片上的查詢(xún)結果
只會(huì )緩存設置了size=0的查詢(xún)對應的結果。不會(huì )緩存hits。但是會(huì )緩存 Aggregations和Suggestions
Cache Key
LRU算法,將整個(gè)JSON查詢(xún)串作為Key,與JSON對象的順序相關(guān),不會(huì )被jvm gc
分片Refresh時(shí)候,Shard Request Cache會(huì )失效。如果Shard對應的數據頻繁發(fā)生變化,該緩存的效率會(huì )很差
配置項
indices.requests.cache.size: “1%”Fielddata Cache
除了Text類(lèi)型,默認都采用doc_values。節約了內存。
Aggregation的Global ordinals也保存在Fielddata cache 中
Text類(lèi)型的字段需要打開(kāi)Fileddata才能對其進(jìn)行聚合和排序
Text經(jīng)過(guò)分詞,排序和聚合效果不佳,建議不要輕易使用。
Segment被合并后,會(huì )失效
配置項,調整該參數避免產(chǎn)生GC(默認無(wú)限制):
Indices.fielddata.cache.sizeSegments Cache
(segments FST數據的緩存),為了加速查詢(xún),FST永駐堆內內存,無(wú)法被GC回收。該部分內存無(wú)法設置大小,長(cháng)期占用50%~70%的堆內存,只能通過(guò)delete index,close index以及force-merge index釋放內存
ES底層存儲采用Lucene(搜索引擎),寫(xiě)入時(shí)會(huì )根據原始數據的內容,分詞,然后生成倒排索引。查詢(xún)時(shí),先通過(guò)查詢(xún)倒排索引找到數據地址(DocID)),再讀取原始數據(行存數據、列存數據)。
但由于Lucene會(huì )為原始數據中的每個(gè)詞都生成倒排索引,數據量較大。所以倒排索引對應的倒排表被存放在磁盤(pán)上。
這樣如果每次查詢(xún)都直接讀取磁盤(pán)上的倒排表,再查詢(xún)目標關(guān)鍵詞,會(huì )有很多次磁盤(pán)IO,嚴重影響查詢(xún)性能。為了解磁盤(pán)IO問(wèn)題,Lucene引入排索引的二級索引FST[Finite State Transducer]。原理上可以理解為前綴樹(shù),加速查詢(xún)
GET _cat/nodes?vGET _nodes/stats/indices?prettyGET _cat/nodes?v&h=name,queryCacheMemory,queryCacheEvictions,requestCacheMemory,request CacheHitCount,request_cache.miss_countGET _cat/nodes?h=name,port,segments.memory,segments.index_writer_memory,fielddata.memory_size,query_cache.memory_size,request_cache.memory_size&v
3)案例分析
如果節點(diǎn)出現了集群整體響應緩慢,也沒(méi)有特別多的數據讀寫(xiě)。但是發(fā)現節點(diǎn)在持續進(jìn)行Full GC。
常見(jiàn)原因:
Segments個(gè)數過(guò)多,導致Full GC
我們可以通過(guò)查看ElasticSearch的內存分析命令發(fā)現:
segments.memory占用很大空間。
解決方案:
通過(guò)force merge,把segments合并成一個(gè)
對于不在寫(xiě)入和更新的索引,可以將其設置成只讀。同時(shí),進(jìn)行force merge 操作。如果問(wèn)題依然存在,則需要考慮擴容。此外,對索引進(jìn)行 force merge,還可以減少對global_ordinals數據結構的構建,減少對fielddata cache的開(kāi)銷(xiāo)
Field data cache 過(guò)大,導致Full GC
我們可以查看ElasticSearch的內存使用,發(fā)現fielddata.memory.size占用很大空間。同時(shí),數據不存在寫(xiě)入和更新,也執行過(guò)segments merge。
解決方案:
將indices.fielddata.cache.size設小,重啟節點(diǎn),堆內存恢復正常
Field data cache的構建比較重,ElasticSearch不會(huì )主動(dòng)釋放,所以這個(gè)值應該設置的保守一些。如果業(yè)務(wù)上確實(shí)有所需要,可以通過(guò)增加節點(diǎn),擴容解決。
復雜的嵌套聚合,導致集群Full GC
節點(diǎn)響應緩慢,持續進(jìn)行Full GC。導出Dump分析。發(fā)現內存中有大量 bucket對象,查看日志,發(fā)現復雜的嵌套聚合
解決方案:
優(yōu)化聚合方式
在大量數據集上進(jìn)行嵌套聚合查詢(xún),需要很大的堆內存來(lái)完成。如果業(yè)務(wù)場(chǎng)景確實(shí)需要。則需要增加硬件進(jìn)行擴展。同時(shí),為了避免這類(lèi)查詢(xún)影響整個(gè)集群,需要設置Circuit Breaker和search.max_buckets的數值
4)斷路器
es有多種斷路器,我們可以合理使用,避免不合理操作引發(fā)的OOM,每個(gè)斷路器可以指定內存使用的限制。
關(guān)于es的斷路器使用可以參考官網(wǎng)文檔:
https://www.elastic.co/cn/blog/improving-node-resiliency-with-the-real-memory-circuit-breaker
4.4. 常用工具
在排查es問(wèn)題時(shí),我們會(huì )使用一些常見(jiàn)的命令來(lái)分析cpu、io、網(wǎng)絡(luò )等問(wèn)題。常見(jiàn)的命令如下
4.4.1 iostat命令
我們這里按照1s的頻率輸出磁盤(pán)信息
iostat -xd 1iops
由r/s(每秒讀次數)和w/s(每秒寫(xiě)次數)組成。
await
平均IO等待時(shí)間,包括硬件處理IO的時(shí)間和在隊列中的等待時(shí)間。
%util
設備的繁忙比
設備執行的I/O時(shí)間與所經(jīng)過(guò)的時(shí)間百分比。當值接近100%時(shí)設備產(chǎn)生飽和。在設備具有并行處理能力的情況下,util達到100%不代表設備沒(méi)有余力處理更多I/O請求。
如果想查看和進(jìn)程關(guān)聯(lián)的信息,可以使用pidstat或者iotop。
例如,下面為iotop的輸出結果

4.4.2 內存
sar命令可以診斷操作系統內存相關(guān)情況。
sar -B
當系統物理內存不足時(shí)。系統回收效率對部署的es節點(diǎn)的性能有較大的影響。我們可以通過(guò)sar -B來(lái)觀(guān)察內存分頁(yè)信息

pgfree/s
每秒被放入空閑列表中的頁(yè)數,如果其他進(jìn)程需要內存,則這些頁(yè)可以被分頁(yè)(paged out)。
pgscank/s
每秒被kswapd守護進(jìn)程掃描的頁(yè)數。
pgscand/s
每秒被直接掃描的頁(yè)數。
pgsteal/s
為了滿(mǎn)足內存需求,系統每秒從緩存(pagecache和swapcache)回收的頁(yè)面數。
%vmeff
代表頁(yè)面回收效率。計算方式為:
pgsteal/(pgscand+pgscank)。
過(guò)低表明虛擬內存存在問(wèn)題,如果在采樣周期內沒(méi)有發(fā)生頁(yè)面掃描,則該值為0或接近100。
我們可以重點(diǎn)關(guān)注vmeff,當為0和接近100時(shí)說(shuō)明內存夠用,其它情況頁(yè)面回收效率過(guò)低,內存也不夠。
sar -w

pswpin/s
每秒換入交換頁(yè)數量
pswpount/s
每秒換出交換頁(yè)的數量
PS:我們需要關(guān)閉內存交換,內存交換會(huì )嚴重損害性能。
4.4.3. cpu
我們知道,操作系統有內核態(tài)和用戶(hù)態(tài),該命令可以輸出相關(guān)信息
vmstat

mpstat
用戶(hù)級(usr)和內核級(sys)的CPU占用百分比
還可以輸出采樣周期內的軟中斷(soft)、硬中斷( irq)占用時(shí)間的百分比

4.4.4. 網(wǎng)絡(luò )
sar -n DEV 1
sar是用來(lái)查看網(wǎng)卡流量的最常用方式,它以字節為單位輸出網(wǎng)絡(luò )傳入和傳出流量。

netstat -anp
統計了進(jìn)程級別連接、監聽(tīng)的端口的信息。

Recv-Q和Send-Q代表該連接在內核中等待發(fā)送和接收的數據長(cháng)度。
如果改數據太多,可能原因為應用程序處理不及時(shí)或者對端的數據接收不及時(shí),比如網(wǎng)絡(luò )擁塞之類(lèi)
本片文章先介紹了es的部署架構,回顧了es節點(diǎn)類(lèi)型以及它們的配置方式,也了解了不同類(lèi)型對硬件的要求不一樣。然后總結了幾種不同的架構模式,比如基礎部署、讀寫(xiě)分離、冷熱分離、異地多活等架構模式,在生產(chǎn)環(huán)境中一般我們推薦讀寫(xiě)分離架構模式,如果可以最好加上冷熱分離,不過(guò)配置可能稍微復雜點(diǎn)。
對于容量規劃與調優(yōu),首先要明確存儲的數據量和使用場(chǎng)景,推薦內存磁盤(pán)比為:搜索類(lèi)比例(1:16),日志類(lèi)(1:48);比如2T的總數據,搜索如果要保持良好的性能的話(huà),每個(gè)節點(diǎn)31*16=496G。每個(gè)節點(diǎn)實(shí)際有400G的存儲空間。那么2T/400G,則需要5個(gè)es存儲節點(diǎn),每個(gè)節點(diǎn)分片數多少合適,文中也有介紹。副本分片數需要根據我們的容錯需求。我們還總結了集群配置和jvm配置相關(guān)的優(yōu)化。
es的使用優(yōu)化,我們分別總結了寫(xiě)入和查詢(xún)的優(yōu)化。寫(xiě)入是其單次數據量、索引refresh、分詞等情況都會(huì )影響其吞吐量,我們需要根據實(shí)際情況來(lái)優(yōu)化。針對于查詢(xún),我們可以使用api工具進(jìn)行分析,分析慢耗時(shí)發(fā)在在哪一步。當es集群出現異常時(shí),如cpu過(guò)高、內存fullgc、卡頓、變紅,我們逐一分析了可能的原因和解決辦法,同時(shí)也介紹了一些常見(jiàn)的診斷工具和監控api。
我們需要先了解es內部運作的原理,這樣才能根據實(shí)際情況正確的設置集群參數和數據模型,還需要結合實(shí)際工作遇到的問(wèn)題不斷的總結經(jīng)驗,才能用好ElasticSearch。
文章導航


聯(lián)系客服