最近解决了一个生产bug,bug的缘由很简单,就是清理缓存的方式不对。原本没啥好说的,可是考虑到咱们有时候确实会在一些小问题上栽跟头,最终决定把这个小故事拿出来跟你们分享下。数据库
风起
有一天在撸代码,忽然有我的加我微信,看头像是个妹子。我第一反应:对方是微商或者卖茶叶的(忍住,别笑)。由于已经有不少次这种加我好友的状况了,问对方是谁就历来没有下文。因此此次我也没有经过,而是像之前同样追问了一句“咱们认识吗”,就没再管它,心想对方确定不回的。而后继续而后继续撸串,哦不,是撸代码。
还没1分钟,对方居然回复了,大意是“我是xxx公司的某某某,有个问题想咨询下”,哇哦,原来是客户。。。赶忙经过验证并问具体啥问题。原来是对方在点某个页面按钮的时候一直提示错误,不能正常进行业务了。缓存
常规操做
和以往同样,我查起了生产log,发现是数据库锁表了。客户是业务型公司,通常不会出现多人同时操做的状况,数据量也不大,生产上历来没有出现过,却是我本地调试的时候常常由于性子急多点几回致使锁表,所以感受这个问题很好解决,让管理员把锁解了就好了。微信
云涌
没有锁了,让客户再试下,客户的反馈“仍是报错”,没道理啊。再查日志,发现已经没有了堆栈信息,为啥还不行呢。
没办法只能看那个时间段全部的log,发现有一行“map缓存中有数据,可能多人同时操做”。
查下代码,发现代码中为了防止同一条数据多人同时操做,加了map做为缓存,数据记录的PK做为key和value。spa
(记住这个图,后面会考)
每次操做的时候将数据put进map,处理完后remove掉。若是map中有相关KV就表示这条记录有人正在操做,则其余人不能操做,抛提示信息。
因而乎问客户“多人同操乎?”,获得的答复是“否”,纳尼?怎可能。日志是不会骗人的啊调试
再查代码
针对map再把代码看一遍,看它put和remove的地方,还有日志打印的地方。终于发现一个问题,
map的清理动做是在try里面正常处理后作的,若是出现异常就不能正常清理了,而map定义的时候为了对象间共享定义成了静态成员变量,
刚才的锁表抛了异常,当时已经put进入到map里面的KV就一直没有机会清掉了,也就是说只要服务不重启,问题会一直坚决的陪着你。日志
对症下药
1.跟领导申请紧急重启服务,保证业务正常进行。
2.修改问题代码,将报错放到finally块。
3.横展开调查其余相似代码是否是也存在这个问题,一并修改。对象
风平浪静
问题解决,对方表示感谢,我也回复不客气,一切回归平静。blog
总结
其实这个缓存清理的问题自己很简单,你们都懂,就和释放数据库链接等状况同样,须要放到finally块里面,
这个即便代码抛异常了也能正常释放或清理。可是就是撸这段代码的时候,由于这样那样的缘由一时没有想到。
若是公司有代码review的环节的话会好不少,若是没有review,那么在写完代码后最好本身review一遍。
不然,万一出现相似的问题真的有点尴尬,正如题目所说“清缓存的姿式不对,真的会出生产bug哦”。
但愿你我从此都能避免这种状况的发生。rem