?
最近解決了一個生產(chǎn)bug,bug的原因很簡單,就是清理緩存的方式不對。本來沒啥好說的,但是考慮到我們有時候確實會在一些小問題上栽跟頭,最終決定把這個小故事拿出來跟大家分享下。
?
風(fēng)起
有一天在擼代碼,突然有個人加我微信,看頭像是個妹子。我第一反應(yīng):對方是微商或者賣茶葉的(忍住,別笑)。因為已經(jīng)有很多次這種加我好友的情況了,問對方是誰就從來沒有下文。所以這次我也沒有通過,而是像以前一樣追問了一句“我們認(rèn)識嗎”,就沒再管它,心想對方肯定不回的。然后繼續(xù)然后繼續(xù)擼串,哦不,是擼代碼。
還沒1分鐘,對方竟然回復(fù)了,大意是“我是xxx公司的某某某,有個問題想咨詢下”,哇哦,原來是客戶。。。趕緊通過驗證并問具體啥問題。原來是對方在點某個頁面按鈕的時候一直提示錯誤,不能正常進(jìn)行業(yè)務(wù)了。
?
常規(guī)操作
和以往一樣,我查起了生產(chǎn)log,發(fā)現(xiàn)是數(shù)據(jù)庫鎖表了??蛻羰菢I(yè)務(wù)型公司,一般不會出現(xiàn)多人同時操作的情況,數(shù)據(jù)量也不大,生產(chǎn)上從來沒有出現(xiàn)過,倒是我本地調(diào)試的時候經(jīng)常因為性子急多點幾次導(dǎo)致鎖表,因此感覺這個問題很好解決,讓管理員把鎖解了就行了。
?
云涌
沒有鎖了,讓客戶再試下,客戶的反饋“還是報錯”,沒道理啊。再查日志,發(fā)現(xiàn)已經(jīng)沒有了堆棧信息,為啥還不行呢。
沒辦法只能看那個時間段所有的log,發(fā)現(xiàn)有一行“map緩存中有數(shù)據(jù),可能多人同時操作”。
查下代碼,發(fā)現(xiàn)代碼中為了防止同一條數(shù)據(jù)多人同時操作,加了map作為緩存,數(shù)據(jù)記錄的PK作為key和value。
(記住這個圖,后面會考)
每次操作的時候?qū)?shù)據(jù)put進(jìn)map,處理完后remove掉。如果map中有相關(guān)KV就表示這條記錄有人正在操作,則其他人不能操作,拋提示信息。
于是乎問客戶“多人同操乎?”,得到的答復(fù)是“否”,納尼?怎可能。日志是不會騙人的啊
?
再查代碼
針對map再把代碼看一遍,看它put和remove的地方,還有日志打印的地方。終于發(fā)現(xiàn)一個問題,
map的清理動作是在try里面正常處理后做的,如果出現(xiàn)異常就不能正常清理了,而map定義的時候為了對象間共享定義成了靜態(tài)成員變量,
剛才的鎖表拋了異常,當(dāng)時已經(jīng)put進(jìn)入到map里面的KV就一直沒有機(jī)會清掉了,也就是說只要服務(wù)不重啟,問題會一直堅定的陪著你。
?
對癥下藥
1.跟領(lǐng)導(dǎo)申請緊急重啟服務(wù),保證業(yè)務(wù)正常進(jìn)行。
2.修改問題代碼,將報錯放到finally塊。
3.橫展開調(diào)查其他類似代碼是不是也存在這個問題,一并修改。
?
風(fēng)平浪靜
問題解決,對方表示感謝,我也回復(fù)不客氣,一切回歸平靜。
?
總結(jié)
其實這個緩存清理的問題本身很簡單,大家都懂,就和釋放數(shù)據(jù)庫連接等情況一樣,需要放到finally塊里面,
這個即使代碼拋異常了也能正常釋放或清理。但是就是擼這段代碼的時候,因為這樣那樣的原因一時沒有想到。
如果公司有代碼review的環(huán)節(jié)的話會好很多,如果沒有review,那么在寫完代碼后最好自己review一遍。
否則,萬一出現(xiàn)類似的問題真的有點尷尬,正如題目所說“清緩存的姿勢不對,真的會出生產(chǎn)bug哦”。
希望你我今后都能避免這種情況的發(fā)生。
熱門工具 換一換