問題背景
在用戶的實(shí)際使用中發(fā)現(xiàn)叼屠,某一簡單查詢,查詢一段時(shí)間內(nèi)符合要求的記錄论颅,查詢老舊數(shù)據(jù)哎垦,響應(yīng)速度在1秒左右,而查詢包含最近數(shù)據(jù)的同類查詢則慢到十秒左右恃疯,且存在超時(shí)的現(xiàn)象漏设。老舊數(shù)據(jù)比如說今年5月份之前的數(shù)據(jù),新數(shù)據(jù)比如說今年6月份的數(shù)據(jù)今妄,對(duì)比的查詢僅僅只有時(shí)間段的差異郑口,沒有排序,也沒有模糊匹配盾鳞。
另外犬性,在出現(xiàn)慢查詢時(shí),CPU利用率幾乎飆升到100%腾仅。
問題分析
是分片的存儲(chǔ)傾斜導(dǎo)致的嗎乒裆?
用戶的數(shù)據(jù)量有幾十TB,幾百億條數(shù)據(jù)推励。首先是懷疑分片分配或者存儲(chǔ)不均勻的問題導(dǎo)致鹤耍,而現(xiàn)場的實(shí)際是該索引一共設(shè)置了1000分片,此后未再設(shè)計(jì)按月份存儲(chǔ)拆分索引這種操作吹艇,也就是所謂5月份或者6月份的記錄數(shù)據(jù)都是疊放在相同的索引分片中惰蜜,均勻分散在1000個(gè)分片里,新老數(shù)據(jù)不存在分布的區(qū)別受神,這邊從兩份查詢結(jié)果命中的分片數(shù)相等也可見一斑抛猖。
是新數(shù)據(jù)段尚未合并導(dǎo)致的嗎?
新的索引數(shù)據(jù)寫入時(shí), ES會(huì)創(chuàng)建新的段财著,通過后臺(tái)的實(shí)際檢測發(fā)現(xiàn)联四,隨機(jī)抽取了一個(gè)分片目錄,里面共有200+的文件數(shù)撑教,其中數(shù)據(jù)段的數(shù)量在80+朝墩,屬于較多的情況。因此首先考慮執(zhí)行一下段合并伟姐。
通過Kibana執(zhí)行POST強(qiáng)制合并的請求時(shí)收苏,往往會(huì)報(bào)請求超時(shí)的錯(cuò)誤,這時(shí)無需去調(diào)大超時(shí)時(shí)間愤兵。因?yàn)檫@個(gè)調(diào)用將阻塞直到合并完成鹿霸。如果http連接丟失,請求將在后臺(tái)繼續(xù)進(jìn)行秆乳,任何新的請求將被阻止懦鼠,直到之前的強(qiáng)制合并完成。
等到觀察到合并執(zhí)行結(jié)束后屹堰,再去嘗試比較查詢速度肛冶,絕對(duì)速度略有提升,但相對(duì)速度仍然有數(shù)倍的差異扯键。方向?qū)α四佬洌蝗珜?duì),問題的根因不在于此忧陪。
查詢緩存的影響扣泊?
如此巨大的速度差異,可能是ES查詢緩存引起的嘶摊。
進(jìn)行了一些簡單的查詢順序調(diào)換,得到的結(jié)果仍然是查詢最新的數(shù)據(jù)較慢评矩。同時(shí)也發(fā)現(xiàn)叶堆,對(duì)慢查詢直接進(jìn)行第二次查詢的時(shí)候,速度確實(shí)特別快斥杜,從十秒到低于1秒虱颗,這應(yīng)該是直接使用緩存的效果了。
那么也不是由于緩存引發(fā)的蔗喂。但這里沒有拿到一手完整的數(shù)據(jù)忘渔,存疑。
分析總結(jié)
這種現(xiàn)象的原因可能是:
- Segments(段):ES將索引劃分為多個(gè)段缰儿,每個(gè)段包含部分文檔畦粮。當(dāng)新文檔被添加到索引中時(shí),ES會(huì)創(chuàng)建新的段。老數(shù)據(jù)存在于舊的段中宣赔,而新數(shù)據(jù)存在于新的段中预麸。查詢舊數(shù)據(jù)比查詢新數(shù)據(jù)快是因?yàn)榕f的段被更頻繁地訪問和緩存,而新的段可能還沒有被完全加載或緩存儒将,導(dǎo)致查詢速度較慢吏祸。
- Merge(合并)操作:ES的合并操作會(huì)將多個(gè)段合并為一個(gè)更大的段,以優(yōu)化查詢性能钩蚊。當(dāng)有新文檔被索引時(shí)贡翘,ES需要執(zhí)行合并操作來壓縮段數(shù)量。這個(gè)合并操作可能會(huì)導(dǎo)致查詢新數(shù)據(jù)較慢砰逻,因?yàn)樵诤喜⑦^程中床估,舊的段可能會(huì)被頻繁地訪問和緩存,而新的段可能需要等待合并完成才能被加載和緩存诱渤。
- Refresh(刷新)操作:ES默認(rèn)每秒執(zhí)行一次刷新操作丐巫,將內(nèi)存中的數(shù)據(jù)寫入磁盤。當(dāng)有新文檔被索引時(shí)勺美,ES需要等待下一次刷新操作才能將新數(shù)據(jù)寫入磁盤并更新索引递胧。因此,在刷新操作之前查詢新數(shù)據(jù)可能會(huì)較慢赡茸,而查詢舊數(shù)據(jù)不會(huì)受到影響缎脾。
為解決以上問題,可以采取以下措施:
- 提高刷新頻率:可以通過調(diào)整刷新間隔來減少新數(shù)據(jù)查詢的延遲占卧,但會(huì)增加寫入操作的開銷遗菠。
- 使用更少的段:可以通過手動(dòng)觸發(fā)合并操作來減少索引中的段數(shù)量,從而提高查詢性能华蜒。
- 預(yù)熱(warm-up):可以在索引啟動(dòng)前對(duì)新數(shù)據(jù)執(zhí)行一些查詢操作辙纬,以提前加載和緩存新數(shù)據(jù)所在的段,從而加速后續(xù)查詢叭喜。
- 設(shè)置查詢優(yōu)先級(jí):可以通過設(shè)置查詢優(yōu)先級(jí)贺拣,給新數(shù)據(jù)的查詢分配更多的資源和處理能力,以提高查詢速度捂蕴。
總結(jié)來說譬涡,ES查詢老數(shù)據(jù)較快、查詢新數(shù)據(jù)較慢是由于ES的索引段劃分啥辨、合并操作涡匀、刷新操作等機(jī)制導(dǎo)致的,通過調(diào)整刷新頻率溉知、優(yōu)化段合并陨瘩、預(yù)熱和設(shè)置查詢優(yōu)先級(jí)等方法可以改善新數(shù)據(jù)查詢的性能腕够。
解決方案
現(xiàn)場的讀寫參數(shù)等不便進(jìn)行調(diào)整,因此我從優(yōu)化查詢語句入手拾酝,發(fā)現(xiàn)業(yè)務(wù)的查詢只涉及3個(gè)字段燕少,分別是2個(gè)term
和一個(gè)range
查詢,這種查詢是無需進(jìn)行評(píng)分的蒿囤。因此推薦將query
語句的must
查詢改為了filter
查詢客们,查詢慢的問題迎刃而解,所有時(shí)間段的查詢都得以秒回材诽。