問題背景
在用戶的實際使用中發(fā)現(xiàn),某一簡單查詢,查詢一段時間內(nèi)符合要求的記錄,查詢老舊數(shù)據(jù),響應(yīng)速度在1秒左右,而查詢包含最近數(shù)據(jù)的同類查詢則慢到十秒左右,且存在超時的現(xiàn)象。老舊數(shù)據(jù)比如說今年5月份之前的數(shù)據(jù),新數(shù)據(jù)比如說今年6月份的數(shù)據(jù),對比的查詢僅僅只有時間段的差異,沒有排序,也沒有模糊匹配。
另外,在出現(xiàn)慢查詢時,CPU利用率幾乎飆升到100%。
問題分析
是分片的存儲傾斜導(dǎo)致的嗎?
用戶的數(shù)據(jù)量有幾十TB,幾百億條數(shù)據(jù)。首先是懷疑分片分配或者存儲不均勻的問題導(dǎo)致,而現(xiàn)場的實際是該索引一共設(shè)置了1000分片,此后未再設(shè)計按月份存儲拆分索引這種操作,也就是所謂5月份或者6月份的記錄數(shù)據(jù)都是疊放在相同的索引分片中,均勻分散在1000個分片里,新老數(shù)據(jù)不存在分布的區(qū)別,這邊從兩份查詢結(jié)果命中的分片數(shù)相等也可見一斑。
是新數(shù)據(jù)段尚未合并導(dǎo)致的嗎?
新的索引數(shù)據(jù)寫入時, ES會創(chuàng)建新的段,通過后臺的實際檢測發(fā)現(xiàn),隨機抽取了一個分片目錄,里面共有200+的文件數(shù),其中數(shù)據(jù)段的數(shù)量在80+,屬于較多的情況。因此首先考慮執(zhí)行一下段合并。
通過Kibana執(zhí)行POST強制合并的請求時,往往會報請求超時的錯誤,這時無需去調(diào)大超時時間。因為這個調(diào)用將阻塞直到合并完成。如果http連接丟失,請求將在后臺繼續(xù)進行,任何新的請求將被阻止,直到之前的強制合并完成。
等到觀察到合并執(zhí)行結(jié)束后,再去嘗試比較查詢速度,絕對速度略有提升,但相對速度仍然有數(shù)倍的差異。方向?qū)α?,但不全對,問題的根因不在于此。
查詢緩存的影響?
如此巨大的速度差異,可能是ES查詢緩存引起的。
進行了一些簡單的查詢順序調(diào)換,得到的結(jié)果仍然是查詢最新的數(shù)據(jù)較慢。同時也發(fā)現(xiàn),對慢查詢直接進行第二次查詢的時候,速度確實特別快,從十秒到低于1秒,這應(yīng)該是直接使用緩存的效果了。
那么也不是由于緩存引發(fā)的。但這里沒有拿到一手完整的數(shù)據(jù),存疑。
分析總結(jié)
這種現(xiàn)象的原因可能是:
- Segments(段):ES將索引劃分為多個段,每個段包含部分文檔。當(dāng)新文檔被添加到索引中時,ES會創(chuàng)建新的段。老數(shù)據(jù)存在于舊的段中,而新數(shù)據(jù)存在于新的段中。查詢舊數(shù)據(jù)比查詢新數(shù)據(jù)快是因為舊的段被更頻繁地訪問和緩存,而新的段可能還沒有被完全加載或緩存,導(dǎo)致查詢速度較慢。
- Merge(合并)操作:ES的合并操作會將多個段合并為一個更大的段,以優(yōu)化查詢性能。當(dāng)有新文檔被索引時,ES需要執(zhí)行合并操作來壓縮段數(shù)量。這個合并操作可能會導(dǎo)致查詢新數(shù)據(jù)較慢,因為在合并過程中,舊的段可能會被頻繁地訪問和緩存,而新的段可能需要等待合并完成才能被加載和緩存。
- Refresh(刷新)操作:ES默認每秒執(zhí)行一次刷新操作,將內(nèi)存中的數(shù)據(jù)寫入磁盤。當(dāng)有新文檔被索引時,ES需要等待下一次刷新操作才能將新數(shù)據(jù)寫入磁盤并更新索引。因此,在刷新操作之前查詢新數(shù)據(jù)可能會較慢,而查詢舊數(shù)據(jù)不會受到影響。
為解決以上問題,可以采取以下措施:
- 提高刷新頻率:可以通過調(diào)整刷新間隔來減少新數(shù)據(jù)查詢的延遲,但會增加寫入操作的開銷。
- 使用更少的段:可以通過手動觸發(fā)合并操作來減少索引中的段數(shù)量,從而提高查詢性能。
- 預(yù)熱(warm-up):可以在索引啟動前對新數(shù)據(jù)執(zhí)行一些查詢操作,以提前加載和緩存新數(shù)據(jù)所在的段,從而加速后續(xù)查詢。
- 設(shè)置查詢優(yōu)先級:可以通過設(shè)置查詢優(yōu)先級,給新數(shù)據(jù)的查詢分配更多的資源和處理能力,以提高查詢速度。
總結(jié)來說,ES查詢老數(shù)據(jù)較快、查詢新數(shù)據(jù)較慢是由于ES的索引段劃分、合并操作、刷新操作等機制導(dǎo)致的,通過調(diào)整刷新頻率、優(yōu)化段合并、預(yù)熱和設(shè)置查詢優(yōu)先級等方法可以改善新數(shù)據(jù)查詢的性能。
解決方案
現(xiàn)場的讀寫參數(shù)等不便進行調(diào)整,因此我從優(yōu)化查詢語句入手,發(fā)現(xiàn)業(yè)務(wù)的查詢只涉及3個字段,分別是2個term和一個range查詢,這種查詢是無需進行評分的。因此推薦將query語句的must查詢改為了filter查詢,查詢慢的問題迎刃而解,所有時間段的查詢都得以秒回。