新聞中心
本篇內(nèi)容主要講解“如何解決Scan的問(wèn)題”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何解決Scan的問(wèn)題”吧!
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),阿勒泰企業(yè)網(wǎng)站建設(shè),阿勒泰品牌網(wǎng)站建設(shè),網(wǎng)站定制,阿勒泰網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,阿勒泰網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
重啟
我入會(huì)的時(shí)候,已經(jīng)有同事在幫忙定位了,俗話說(shuō)的好,重啟能解決 80% 的問(wèn)題,如果重啟解決不了,那肯定是重啟的次數(shù)還不夠,呸,不對(duì),重啟解決不了,就真的要去定位了。
事實(shí)證明,重啟后走一波壓測(cè)依然沒(méi)什么用,1000 個(gè)并發(fā),平均響應(yīng)時(shí)間在 3~4 秒,連續(xù)壓了幾次都是這樣的結(jié)果。
升級(jí)配置
重啟看來(lái)是無(wú)效了,進(jìn)入第二個(gè)階段——升級(jí)配置,2 臺(tái) 4 核 8G 的實(shí)例升級(jí)到 6 臺(tái) 8 核 16G,數(shù)據(jù)庫(kù)的配置也翻了一倍,能用錢(qián)解決的問(wèn)題,我們一般不會(huì)投入太多的人力!
事實(shí)證明,加配置也沒(méi)什么卵用,1000 個(gè)并發(fā),壓測(cè)的平均響應(yīng)時(shí)間還是在 3~4 秒。
有點(diǎn)意思,此時(shí),我介入了。
查看監(jiān)控
我上線之后,查看了一下監(jiān)控,實(shí)例的 CPU、內(nèi)存、磁盤(pán)、網(wǎng)絡(luò) IO、JVM 堆內(nèi)存使用情況好像都沒(méi)啥問(wèn)題,這真是個(gè)頭疼的問(wèn)題。
本地壓測(cè)
我們分成兩波同學(xué),一波去準(zhǔn)備本地壓測(cè),一波繼續(xù)分析,經(jīng)過(guò)本地壓測(cè),我們發(fā)現(xiàn),本地環(huán)境,單機(jī),1000 個(gè)并發(fā),妥妥的,毛問(wèn)題都沒(méi)有,平均響應(yīng)基本維持在幾百毫秒。
看來(lái),確實(shí)跟服務(wù)本身沒(méi)有問(wèn)題。
代碼走查
實(shí)在沒(méi)有辦法了,拿出代碼,一群大老爺們一起看代碼,研發(fā)同學(xué)給我們講解業(yè)務(wù)邏輯,當(dāng)然,他已經(jīng)被各位大佬給罵死了,寫(xiě)的什么破代碼。
其實(shí),在我介入之前,他們已經(jīng)改過(guò)一波代碼了,有個(gè)地方把 redis 命令 scan 改成了 keys *,這里埋了個(gè)坑,但是,現(xiàn)在不是主要問(wèn)題,后面我們會(huì)說(shuō)。
代碼一路走讀下來(lái),發(fā)現(xiàn)有很多的 redis 操作,還有個(gè) for 循環(huán)里面在調(diào) redis 的 get 命令,其他的都是常規(guī)的數(shù)據(jù)庫(kù)操作,而且都加了索引的。
所以,初步排查,數(shù)據(jù)庫(kù)這里應(yīng)該是沒(méi)有什么問(wèn)題,主要問(wèn)題可能還是集中在 redis 這塊,調(diào)用太頻繁了。
加日志
代碼走查下來(lái),除了那個(gè) scan 改成了 keys *(這個(gè)我還不知道),基本上沒(méi)有什么問(wèn)題,加日志吧, 一小段一小段的加上日志,OK,重啟服務(wù),壓測(cè)來(lái)一波。
當(dāng)然了,結(jié)果沒(méi)有什么變化,分析日志。
通過(guò)日志,我們發(fā)現(xiàn),調(diào)用 redis 的時(shí)候時(shí)而很快,時(shí)而很慢,看起來(lái)像是連接池不夠的樣子,也就是一批請(qǐng)求先行,一批請(qǐng)求在等待空閑的 redis 連接。
修改 redis 連接數(shù)
查看 redis 配置,用的是單機(jī)模式,1G 內(nèi)存, 連接數(shù)默認(rèn)的 8,客戶(hù)端還是比較老的 jedis,果斷改成 springboot 默認(rèn)的 lettuce,連接數(shù)先調(diào)整為 50,重啟服務(wù),壓一波。
平均響應(yīng)時(shí)間從 3~4 秒降到了 2~3 秒,并不明顯,繼續(xù)加大連接數(shù),因?yàn)槲覀兪?1000 個(gè)并發(fā),每個(gè)請(qǐng)求都有很多次 redis 操作,所以,肯定會(huì)有等待,這次我們把連接數(shù)直接干到了 1000,重啟服務(wù),壓一波。
事實(shí)證明,并沒(méi)有明顯地提升。
再次查看日志
此時(shí),已經(jīng)沒(méi)有什么好的解決辦法了,我們?cè)俅位氐饺罩局?,查?redis 相關(guān)操作的時(shí)間,發(fā)現(xiàn) 99% 的 get 操作都是很快返回的,基本上是在 0~5 毫秒之間,但是,總有那么幾個(gè)達(dá)到了 800~900 毫秒才返回。
我們以為 redis 這塊沒(méi)什么問(wèn)題了。但是,壓測(cè)了好幾次,時(shí)間一直提不上去。
很無(wú)奈了,此時(shí),已經(jīng)半夜 3 點(diǎn)多了,領(lǐng)導(dǎo)發(fā)話,把 XX 云的人喊起來(lái)。
云排查
最后,我們把 XX 云相關(guān)的人員喊起來(lái)一起排查問(wèn)題,當(dāng)然,他們是不情愿的,但是,誰(shuí)讓我們給錢(qián)了呢!
XX 云的負(fù)責(zé)人,把 redis 的專(zhuān)家搞起來(lái),幫我們看了下 redis 的指標(biāo),最后,發(fā)現(xiàn)是 redis 的帶寬滿(mǎn)了,然后觸發(fā)了限流機(jī)制。
他們臨時(shí)把 redis 的帶寬增大三倍,讓我們?cè)賶簻y(cè)一波。握了顆草,平均響應(yīng)時(shí)間一下子降到了 200~300 毫秒!!!!
真的是握了顆草了,這就有點(diǎn)坑了,你限流就算了,帶寬滿(mǎn)了也不報(bào)警一下的么......
這真是個(gè)蛋疼的問(wèn)題。到這里,我們以為問(wèn)題就這樣解決了,領(lǐng)導(dǎo)們也去睡覺(jué)了!
上生產(chǎn)
既然問(wèn)題原因找到了,那就上生產(chǎn)壓一波吧!我們讓 XX 云的專(zhuān)家把生產(chǎn)的帶寬也增大了三倍大小。
從生產(chǎn)提交拉一個(gè) hotfix 分支,關(guān)閉簽名,重啟服務(wù),壓測(cè)走一波。完蛋,生產(chǎn)環(huán)境更差,平均響應(yīng)時(shí)間在 5~6 秒。
測(cè)試環(huán)境我們是改了連接池配置的,生產(chǎn)環(huán)境還是 jedis,改之,走一波。并沒(méi)有什么實(shí)際作用,還是 5~6 秒。
真是個(gè)蛋疼的問(wèn)題。
查看監(jiān)控
查看 XX 云中 redis 的監(jiān)控,這次帶寬、流控都是正常的。
這次不正常的變成了 CPU,redis 的 CPU 壓測(cè)的時(shí)候直接飆到了 100%,導(dǎo)到應(yīng)用響應(yīng)緩慢。
再次喚醒 XX 云 redis 專(zhuān)家
已經(jīng)凌晨四點(diǎn)多了,大家已經(jīng)沒(méi)什么思路了,XX 云的 redis 專(zhuān)家,你給我再起來(lái)!
再次喚醒 XX 云的 redis 專(zhuān)家,幫我們分析了下后臺(tái),發(fā)現(xiàn) 10 分鐘內(nèi)進(jìn)行了 14 萬(wàn)次 scan......
萬(wàn)惡的 scan
詢(xún)問(wèn)研發(fā)人員哪里用到了 scan(前面他們改的,我不知道),發(fā)現(xiàn),每次請(qǐng)求都會(huì)調(diào)用 scan 去拿某個(gè)前綴開(kāi)頭的 key,每次掃描 1000 條數(shù)據(jù),查看 redis 鍵總數(shù),大概有 11 萬(wàn)條。
也就是說(shuō),一個(gè)請(qǐng)求就要 scan 100 次,1000 并發(fā),大概就是 10 幾萬(wàn)次 scan。
我們知道,redis 中 scan 和 keys * 是要進(jìn)行全表掃描的,非常消耗 CPU,14 萬(wàn)次 scan 操作,直接讓 CPU 上天了。
為什么測(cè)試環(huán)境 CPU 沒(méi)有上天呢?
對(duì)比了下,測(cè)試環(huán)境和生產(chǎn)環(huán)境 redis 的鍵總數(shù),測(cè)試環(huán)境只有 900 個(gè) key,每次請(qǐng)求也就 scan 一次或者 keys * 一次,毛線問(wèn)題都沒(méi)有。
為什么生產(chǎn)環(huán)境有這么多 key?
詢(xún)問(wèn)研發(fā)人員,為什么生產(chǎn)環(huán)境有這么多 key,沒(méi)有設(shè)置過(guò)期時(shí)間嗎?
研發(fā)人員說(shuō)設(shè)置了的,是另一個(gè)同事寫(xiě)的代碼,打開(kāi)代碼,真是一段魔性的代碼,具體代碼我就不方便貼出來(lái)了,里面有根據(jù)條件判斷要不要設(shè)置過(guò)期時(shí)間,經(jīng)過(guò)分析,大部分情況下,都沒(méi)有設(shè)置過(guò)期時(shí)間成功。
當(dāng)前解決辦法
此時(shí),已經(jīng)凌晨 4 點(diǎn)半了,雖然大家還很興奮,但是,經(jīng)過(guò)領(lǐng)導(dǎo)決策,暫時(shí)先不動(dòng)了。
因?yàn)?,目?A 系統(tǒng)已經(jīng)暫停調(diào)用 B 系統(tǒng)了,所以,此時(shí) B 系統(tǒng)可以說(shuō)流量幾乎為 0 了。
我們白天再分兩個(gè)階段來(lái)修復(fù)這個(gè)問(wèn)題:
第一步,先清理掉生產(chǎn)環(huán)境 redis 的數(shù)據(jù),只保留一小部分必要的數(shù)據(jù)。
第二步,修改 scan 某前綴開(kāi)頭的數(shù)據(jù),改成 hash 存儲(chǔ),這樣可以減少掃描的范圍。
好了,本次生產(chǎn)事故排查就到這里了。
到此,相信大家對(duì)“如何解決Scan的問(wèn)題”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!
本文標(biāo)題:如何解決Scan的問(wèn)題
文章地址:http://www.dlmjj.cn/article/gsijdp.html