Elasticsearch 集群典型報(bào)錯(cuò)日志"逆向"分析
1、集群環(huán)境及存在問(wèn)題
1.1 集群環(huán)境
- 1 臺(tái)宿主機(jī),2 個(gè) ES 節(jié)點(diǎn)。
- 宿主機(jī)配置:56 核 CPU, 256G 內(nèi)存,普通非SSD 磁盤
- 宿主機(jī)除了部署 ES 集群兩個(gè)節(jié)點(diǎn),還部署了其他服務(wù)如 redis、其他(不詳)。
1.2 索引分片
- 單索引 700 GB 左右。
- 20 個(gè)分片。
1.3 改動(dòng)過(guò)如下配置
圖片
1.4 存在問(wèn)題
Elasticsearch 查詢特別慢,內(nèi)存使用率 93%, 現(xiàn)在沒(méi)什么解決思路。
————問(wèn)題來(lái)自球友:https://t.zsxq.com/LcRV0
2、僅如上信息,可以發(fā)現(xiàn)的問(wèn)題
2.1 存在典型問(wèn)題
兩節(jié)點(diǎn)分布在一臺(tái)機(jī)器,還有混部了一些其他的服務(wù)。
本質(zhì)是兩虛擬機(jī)共享一個(gè)實(shí)體服務(wù)器。
混合部署了 Redis 等服務(wù),這是大問(wèn)題。
Redis 屬于內(nèi)存數(shù)據(jù)庫(kù),“吃內(nèi)存”厲害。我們一般不建議這么搞,官方也不建議這么搞。
2.2 盲目修改集群配置,可能帶來(lái)潛在風(fēng)險(xiǎn)
其中,search.max_buckets 默認(rèn)值:10000?,F(xiàn)在擴(kuò)大了1000倍,改成了 1000 萬(wàn)。
該配置項(xiàng)用于限制 Elasticsearch 中聚合查詢(如 histogram 聚合)中返回的最大桶數(shù)。過(guò)高的桶數(shù)可能會(huì)導(dǎo)致內(nèi)存使用過(guò)多,影響集群性能。
其中,thread_pool.write.queue_size 默認(rèn)值:200?,F(xiàn)在改成 2048,擴(kuò)大了 10 倍+。
該配置項(xiàng)用于指定寫入操作的線程池隊(duì)列大小,當(dāng)隊(duì)列滿時(shí),新的寫入請(qǐng)求將被拒絕。
增大隊(duì)列大小可以緩解寫入壓力,但也會(huì)增加內(nèi)存消耗。其中,indices.fielddata.cache.size 默認(rèn)值:未設(shè)置具體默認(rèn)值(動(dòng)態(tài)分配),
該配置項(xiàng)用于限制字段數(shù)據(jù)緩存的大小,默認(rèn)情況下是根據(jù) JVM 堆內(nèi)存動(dòng)態(tài)調(diào)整??梢允褂冒俜直缺硎荆?20% 表示使用最大可用堆內(nèi)存的 20% 作為緩存。
也就是這個(gè)支持動(dòng)態(tài)調(diào)整的,咱們給寫死了。
上述修改其實(shí)都經(jīng)不起推敲和驗(yàn)證,非常的“大膽”,但出問(wèn)題往往也會(huì)超出咱們的預(yù)期。
2.2 其他問(wèn)題不明顯
- 疑似問(wèn)題1:?jiǎn)嗡饕?00g左右, 分片20?單分片大小35g,具體單文檔細(xì)節(jié)不詳。
- 疑似問(wèn)題2:只有2臺(tái)機(jī)器。本質(zhì)兩臺(tái)機(jī)器角色都具備:主節(jié)點(diǎn)、數(shù)據(jù)節(jié)點(diǎn)角色,其中一臺(tái)還充當(dāng)協(xié)調(diào)節(jié)點(diǎn)角色。
- 疑似問(wèn)題3:癥狀提及的查詢慢問(wèn)題,需要給出慢查詢?nèi)罩?,需要給出監(jiān)控指標(biāo)數(shù)據(jù),需要描述一下業(yè)務(wù),需要給出檢索的DSL語(yǔ)句。
3、拿到集群日志,一切變得明朗
圖片
如上截圖為兩個(gè)節(jié)點(diǎn)的日志,-02-1 為主節(jié)點(diǎn)日志,-02-2 為另外一個(gè)節(jié)點(diǎn)的日志。
4、主節(jié)點(diǎn)日志“逆向”分析
4.1 test-1016-2024-08-02-1.log 日志含拒絕請(qǐng)求“9790”次
從最早日期:[2024-08-02T17:15:54,487
到最晚日期:[2024-08-02T17:28:57,460]
累計(jì)時(shí)長(zhǎng):13 分 2.973 秒。
共有如下類似相同報(bào)錯(cuò):9790 次。
日志截取如下:
Caused by: org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.common.util.concurrent.TimedRunnable@5ccc5247 on QueueResizingEsThreadPoolExecutor[name = slav1/search, queue capacity = 1000, min queue capacity = 1000, max queue capacity = 1000, frame size = 2000, targeted response rate = 1s, task execution EWMA = 12.2ms, adjustment amount = 50, org.elasticsearch.common.util.concurrent.QueueResizingEsThreadPoolExecutor@10c62020[Running, pool size = 85, active threads = 85, queued tasks = 1000, completed tasks = 370806]]
也就是說(shuō),當(dāng)前節(jié)點(diǎn)已經(jīng)高負(fù)荷扛不住了。
圖片
上述錯(cuò)誤是由于 Elasticsearch 線程池飽和導(dǎo)致的。這具體表現(xiàn)在 EsRejectedExecutionException 中,表示有任務(wù)被拒絕執(zhí)行。
詳細(xì)原因拆解如下:
- QueueResizingEsThreadPoolExecutor 飽和
報(bào)錯(cuò)信息顯示 search 線程池的隊(duì)列已經(jīng)達(dá)到最大容量(queue capacity = 1000),并且活動(dòng)線程數(shù)已經(jīng)達(dá)到最大(active threads = 85),所以新任務(wù)被拒絕執(zhí)行。
- 任務(wù)積壓
報(bào)錯(cuò)信息中提到有 1000 個(gè)任務(wù)在隊(duì)列中等待執(zhí)行,說(shuō)明當(dāng)前系統(tǒng)的負(fù)載很高,可能是因?yàn)椴樵冋?qǐng)求過(guò)多或請(qǐng)求處理時(shí)間較長(zhǎng)。
- 搜索請(qǐng)求過(guò)多或復(fù)雜
從報(bào)錯(cuò)信息看,搜索請(qǐng)求的參數(shù)和查詢條件比較復(fù)雜(包含多重布爾查詢、排序等,見(jiàn) 4.2 的 DSL 語(yǔ)句),這可能導(dǎo)致了較高的計(jì)算和處理時(shí)間。
可能的解決方案探討:
- 方案1:增加節(jié)點(diǎn)資源
增加 Elasticsearch 集群中的節(jié)點(diǎn)數(shù),或者增加現(xiàn)有節(jié)點(diǎn)的資源(CPU、內(nèi)存等),以分擔(dān)負(fù)載。
看老板給不給硬件投入支持。
- 方案2:優(yōu)化查詢
簡(jiǎn)化查詢條件,減少不必要的字段返回和高亮顯示等操作,盡量?jī)?yōu)化查詢性能。見(jiàn)4.2 章節(jié)分析。
- 方案3:調(diào)整線程池設(shè)置
調(diào)整 search 線程池的配置,如增大 queue capacity 和 pool size,以便處理更多的并發(fā)請(qǐng)求。
但前提:必須結(jié)合硬件資源進(jìn)行合理調(diào)整,而不是盲改 100倍、1000倍甚至更大的值。
4.2 打開(kāi)slow_log 慢日志后,DSL語(yǔ)句顯現(xiàn)。
Elasticsearch 日志能否把全部請(qǐng)求打印出來(lái)?
圖片
4.2.1 問(wèn)題1:"track_total_hits": 2147483647
問(wèn)題描述:將 track_total_hits 設(shè)置為 2147483647(即 2^31-1)是非常高的一個(gè)值,會(huì)導(dǎo)致性能問(wèn)題。
- 原因:
(1)性能消耗大。
計(jì)算所有匹配文檔的總數(shù)需要遍歷所有匹配的文檔,這對(duì)于大規(guī)模數(shù)據(jù)集來(lái)說(shuō)是非常耗時(shí)和耗資源的操作。
(2)不必要的精確度。
通常用戶并不需要一個(gè)如此精確的匹配數(shù)量,大部分情況下一個(gè)較小的估算值已經(jīng)足夠。
Elasticsearch 8.X 聚合查詢下的精度問(wèn)題及其解決方案
- 推薦優(yōu)化后的解決方案:
(1)合理設(shè)置 track_total_hits
將 track_total_hits 設(shè)置為 true 或者一個(gè)合理的數(shù)值,例如 10000,以滿足大多數(shù)統(tǒng)計(jì)需求,同時(shí)減少系統(tǒng)負(fù)擔(dān)。
(2)分頁(yè)處理
通過(guò)分頁(yè)獲取數(shù)據(jù),而不是一次性獲取大量匹配文檔的總數(shù)。
干貨 | 全方位深度解讀 Elasticsearch 分頁(yè)查詢
4.2.2 問(wèn)題2:基于腳本排序
問(wèn)題描述:腳本排序會(huì)極大地影響查詢性能,尤其是在處理大量數(shù)據(jù)時(shí)。
原因:
- (1)計(jì)算開(kāi)銷大
腳本排序需要在每個(gè)匹配的文檔上執(zhí)行腳本計(jì)算,這會(huì)導(dǎo)致高額的 CPU 開(kāi)銷。
- (2)緩存難以利用
腳本排序結(jié)果難以緩存,因?yàn)槊看握?qǐng)求可能都會(huì)涉及不同的計(jì)算邏輯和參數(shù)。
- 推薦解決方案
(1)預(yù)計(jì)算字段
盡量將排序邏輯預(yù)計(jì)算成字段,存儲(chǔ)在文檔中,避免在查詢時(shí)實(shí)時(shí)計(jì)算。
例如,預(yù)先計(jì)算并存儲(chǔ)評(píng)分、排名等,可以借助 ingest pipeline 預(yù)處理實(shí)現(xiàn)。
這就是咱們之前多次強(qiáng)調(diào)過(guò)的“空間換時(shí)間”。
Elasticsearch的ETL利器——Ingest節(jié)點(diǎn)
Elasticsearch 預(yù)處理沒(méi)有奇技淫巧,請(qǐng)先用好這一招!
(2)優(yōu)化腳本
如果必須使用腳本排序,確保腳本盡可能簡(jiǎn)單和高效。使用 Painless 腳本語(yǔ)言并確保腳本已編譯優(yōu)化。最好別用!
(3)索引優(yōu)化
使用合適的索引結(jié)構(gòu)和字段類型,確保查詢性能和排序效率。
4.2.3 問(wèn)題3:Mapping 中有超級(jí)多字段,僅 includes 就有:41 個(gè) 字段。
Mapping 中包含過(guò)多字段,尤其是查詢時(shí) _source 包含大量字段,會(huì)增加查詢負(fù)擔(dān)。
原因:
(1)I/O 開(kāi)銷大
每次查詢需要從磁盤讀取大量字段數(shù)據(jù),增加了 I/O 開(kāi)銷。
(2)網(wǎng)絡(luò)傳輸慢
返回的數(shù)據(jù)量大,增加了網(wǎng)絡(luò)傳輸時(shí)間,影響響應(yīng)速度。
(3)內(nèi)存消耗大
在返回大量字段數(shù)據(jù)(41個(gè)字段的數(shù)據(jù))時(shí),會(huì)占用較多內(nèi)存,影響系統(tǒng)性能。
- 建議解決方案:
(1)按需返回字段
僅在 _source 中包含必要的字段,減少數(shù)據(jù)量。例如,只包含用戶實(shí)際需要顯示或處理的字段。
(2)字段分類管理
將常用字段和不常用字段分開(kāi)管理,常用字段可以集中存儲(chǔ)和索引,不常用字段可以進(jìn)行更高效的壓縮和存儲(chǔ)。
Elasticsearch 8.x 存儲(chǔ)有無(wú)壓縮?能壓縮到多少?
(3)動(dòng)態(tài)字段處理
考慮使用動(dòng)態(tài)字段(借助運(yùn)行時(shí)字段實(shí)現(xiàn))或字段別名,在需要時(shí)動(dòng)態(tài)擴(kuò)展,而不是在 Mapping 中預(yù)先定義所有可能的字段。
4.3 No search context found for id [XXXXXXX],報(bào)錯(cuò):236次。
如下錯(cuò)誤:
org.elasticsearch.search.SearchContextMissingException: No search context found for id [208049],
在 13 分 2.973 秒內(nèi)共發(fā)生 236 次。
圖片
這表明在執(zhí)行 Scroll 查詢時(shí),某些查詢上下文已經(jīng)丟失或超時(shí)。
[2024-08-02T12:05:44,520][DEBUG][o.e.a.s.TransportSearchScrollAction] [slave] [208049] Failed to execute query phase
org.elasticsearch.transport.RemoteTransportException: [slav1][172.17.0.1:29302][indices:data/read/search[phase/query/scroll]]
Caused by: org.elasticsearch.search.SearchContextMissingException: No search context found for id [208049]
4.3.1 “上下文丟失”可能的原因分析
- 查詢上下文過(guò)期 Scroll 查詢上下文默認(rèn)在保持不活動(dòng)狀態(tài)下只會(huì)持續(xù)一段時(shí)間(默認(rèn) 1 分鐘)。如果查詢處理時(shí)間超過(guò)此時(shí)間,上下文會(huì)被清除,從而導(dǎo)致此錯(cuò)誤。
- 高并發(fā)導(dǎo)致上下文管理混亂 在高并發(fā)場(chǎng)景下,大量 Scroll 查詢請(qǐng)求可能導(dǎo)致系統(tǒng)無(wú)法及時(shí)管理和維護(hù)這些上下文,造成上下文丟失。
- 節(jié)點(diǎn)重啟或崩潰 執(zhí)行 Scroll 查詢的節(jié)點(diǎn)如果在查詢過(guò)程中重啟或崩潰,會(huì)導(dǎo)致查詢上下文丟失。
4.3.2 解決方案
- 方案1:增加 Scroll 上下文的保持時(shí)間
需要排查咱們做了啥?
在 Scroll 查詢請(qǐng)求中增加 scroll 參數(shù),例如設(shè)置為 5 分鐘:
{
"scroll": "5m"
}
根據(jù)查詢復(fù)雜度和數(shù)據(jù)量調(diào)整保持時(shí)間,確保足夠長(zhǎng)的時(shí)間完成查詢。
如果數(shù)據(jù)量不大或可以分段處理,使用常規(guī)分頁(yè)查詢代替 Scroll 查詢,減少對(duì)上下文的依賴。
- 方案二:優(yōu)化查詢性能 簡(jiǎn)化查詢條件,減少不必要的計(jì)算,提升查詢速度。
如前所述,“空間換時(shí)間”,預(yù)先計(jì)算和緩存部分查詢結(jié)果,減少實(shí)時(shí)計(jì)算量。
5、非主節(jié)點(diǎn)日志“逆向分析”
除了類似主節(jié)點(diǎn)報(bào)錯(cuò)外,非主節(jié)點(diǎn)報(bào)錯(cuò)如下:
[2024-08-02T17:41:21,517][WARN
org.elasticsearch.cluster.block.ClusterBlockException: blocked by: [SERVICE_UNAVAILABLE/2/no master];
圖片
大致推測(cè):[2024-08-02T17:41:21,517] 主節(jié)點(diǎn)宕機(jī)了。
5.1 問(wèn)題描述
上述日志報(bào)錯(cuò)表明 Elasticsearch 集群當(dāng)前沒(méi)有主節(jié)點(diǎn)(master node)。
在 Elasticsearch 集群中,主節(jié)點(diǎn)負(fù)責(zé)管理集群狀態(tài)和元數(shù)據(jù)(例如索引和節(jié)點(diǎn)信息)。如果集群中沒(méi)有主節(jié)點(diǎn),整個(gè)集群會(huì)變得不可用,導(dǎo)致無(wú)法執(zhí)行任何操作,包括索引和查詢。
5.2 原因猜測(cè)
- 主節(jié)點(diǎn)故障:當(dāng)前主節(jié)點(diǎn)可能已經(jīng)發(fā)生故障或崩潰(猜測(cè)就是第4部分分析的,扛不住壓力導(dǎo)致宕機(jī))。
- 資源不足:主節(jié)點(diǎn)所在的物理機(jī)器資源不足(如內(nèi)存、CPU),導(dǎo)致主節(jié)點(diǎn)崩潰。
6、小結(jié)
通過(guò)合理配置和優(yōu)化,Elasticsearch 集群的性能問(wèn)題是可以逐步解決的。
但,爆改集群默認(rèn)配置是不建議的。
關(guān)鍵在于合理分配資源,優(yōu)化查詢和索引操作,同時(shí)結(jié)合監(jiān)控工具和日志分析,及時(shí)發(fā)現(xiàn)并解決潛在問(wèn)題。
希望上述分析和建議能夠幫助大家更好地管理和優(yōu)化 Elasticsearch 集群,提高系統(tǒng)的穩(wěn)定性和響應(yīng)速度。
第一部分提到的集群配置、節(jié)點(diǎn)角色劃分、分片大小、文檔大小、文檔映射、檢索語(yǔ)句、監(jiān)控指標(biāo)等都值得進(jìn)一步深入探討......