清緩存的姿勢不對,真的會出生產bug哦

  • 2019 年 10 月 3 日
  • 筆記

 

最近解決了一個生產bug,bug的原因很簡單,就是清理緩存的方式不對。本來沒啥好說的,但是考慮到我們有時候確實會在一些小問題上栽跟頭,最終決定把這個小故事拿出來跟大家分享下。

 

風起
有一天在擼代碼,突然有個人加我微信,看頭像是個妹子。我第一反應:對方是微商或者賣茶葉的(忍住,別笑)。因為已經有很多次這種加我好友的情況了,問對方是誰就從來沒有下文。所以這次我也沒有通過,而是像以前一樣追問了一句“我們認識嗎”,就沒再管它,心想對方肯定不回的。然後繼續然後繼續擼串,哦不,是擼代碼。
還沒1分鐘,對方竟然回復了,大意是“我是xxx公司的某某某,有個問題想諮詢下”,哇哦,原來是客戶。。。趕緊通過驗證並問具體啥問題。原來是對方在點某個頁面按鈕的時候一直提示錯誤,不能正常進行業務了。

 

常規操作
和以往一樣,我查起了生產log,發現是數據庫鎖表了。客戶是業務型公司,一般不會出現多人同時操作的情況,數據量也不大,生產上從來沒有出現過,倒是我本地調試的時候經常因為性子急多點幾次導致鎖表,因此感覺這個問題很好解決,讓管理員把鎖解了就行了。

 

雲涌
沒有鎖了,讓客戶再試下,客戶的反饋“還是報錯”,沒道理啊。再查日誌,發現已經沒有了堆棧信息,為啥還不行呢。
沒辦法只能看那個時間段所有的log,發現有一行“map緩存中有數據,可能多人同時操作”。
查下代碼,發現代碼中為了防止同一條數據多人同時操作,加了map作為緩存,數據記錄的PK作為key和value。

(記住這個圖,後面會考)
每次操作的時候將數據put進map,處理完後remove掉。如果map中有相關KV就表示這條記錄有人正在操作,則其他人不能操作,拋提示信息。
於是乎問客戶“多人同操乎?”,得到的答覆是“否”,納尼?怎可能。日誌是不會騙人的啊

 

再查代碼
針對map再把代碼看一遍,看它put和remove的地方,還有日誌打印的地方。終於發現一個問題,
map的清理動作是在try裏面正常處理後做的,如果出現異常就不能正常清理了,而map定義的時候為了對象間共享定義成了靜態成員變量,
剛才的鎖表拋了異常,當時已經put進入到map裏面的KV就一直沒有機會清掉了,也就是說只要服務不重啟,問題會一直堅定的陪着你。

 

對症下藥
1.跟領導申請緊急重啟服務,保證業務正常進行。
2.修改問題代碼,將報錯放到finally塊。
3.橫展開調查其他類似代碼是不是也存在這個問題,一併修改。

 

風平浪靜
問題解決,對方表示感謝,我也回復不客氣,一切回歸平靜。

 

總結
其實這個緩存清理的問題本身很簡單,大家都懂,就和釋放數據庫連接等情況一樣,需要放到finally塊裏面,
這個即使代碼拋異常了也能正常釋放或清理。但是就是擼這段代碼的時候,因為這樣那樣的原因一時沒有想到。
如果公司有代碼review的環節的話會好很多,如果沒有review,那麼在寫完代碼後最好自己review一遍。
否則,萬一出現類似的問題真的有點尷尬,正如題目所說“清緩存的姿勢不對,真的會出生產bug哦”。
希望你我今後都能避免這種情況的發生。