清缓存的姿势不对,真的会出生产bug哦

最近解决了一个生产bug,bug的原因很简单,就是清理缓存的方式不对。本来没啥好说的,但是考虑到我们有时候确实会在一些小问题上栽跟头,最终决定把这个小故事拿出来跟大家分享下。风起有一天在撸代码,突然

大家好,又见面了,我是全栈君。

清缓存的姿势不对,真的会出生产bug哦

 

最近解决了一个生产bug,bug的原因很简单,就是清理缓存的方式不对。本来没啥好说的,但是考虑到我们有时候确实会在一些小问题上栽跟头,最终决定把这个小故事拿出来跟大家分享下。

 

风起
有一天在撸代码,突然有个人加我微信,看头像是个妹子。我第一反应:对方是微商或者卖茶叶的(忍住,别笑)。因为已经有很多次这种加我好友的情况了,问对方是谁就从来没有下文。所以这次我也没有通过,而是像以前一样追问了一句“我们认识吗”,就没再管它,心想对方肯定不回的。然后继续然后继续撸串,哦不,是撸代码。
还没1分钟,对方竟然回复了,大意是“我是xxx公司的某某某,有个问题想咨询下”,哇哦,原来是客户。。。赶紧通过验证并问具体啥问题。原来是对方在点某个页面按钮的时候一直提示错误,不能正常进行业务了。

 

常规操作
和以往一样,我查起了生产log,发现是数据库锁表了。客户是业务型公司,一般不会出现多人同时操作的情况,数据量也不大,生产上从来没有出现过,倒是我本地调试的时候经常因为性子急多点几次导致锁表,因此感觉这个问题很好解决,让管理员把锁解了就行了。

 

云涌
没有锁了,让客户再试下,客户的反馈“还是报错”,没道理啊。再查日志,发现已经没有了堆栈信息,为啥还不行呢。
没办法只能看那个时间段所有的log,发现有一行“map缓存中有数据,可能多人同时操作”。
查下代码,发现代码中为了防止同一条数据多人同时操作,加了map作为缓存,数据记录的PK作为key和value。
清缓存的姿势不对,真的会出生产bug哦

(记住这个图,后面会考)
每次操作的时候将数据put进map,处理完后remove掉。如果map中有相关KV就表示这条记录有人正在操作,则其他人不能操作,抛提示信息。
于是乎问客户“多人同操乎?”,得到的答复是“否”,纳尼?怎可能。日志是不会骗人的啊

 

再查代码
针对map再把代码看一遍,看它put和remove的地方,还有日志打印的地方。终于发现一个问题,
map的清理动作是在try里面正常处理后做的,如果出现异常就不能正常清理了,而map定义的时候为了对象间共享定义成了静态成员变量,
刚才的锁表抛了异常,当时已经put进入到map里面的KV就一直没有机会清掉了,也就是说只要服务不重启,问题会一直坚定的陪着你。
清缓存的姿势不对,真的会出生产bug哦

 

对症下药
1.跟领导申请紧急重启服务,保证业务正常进行。
2.修改问题代码,将报错放到finally块。
3.横展开调查其他类似代码是不是也存在这个问题,一并修改。

 

风平浪静
问题解决,对方表示感谢,我也回复不客气,一切回归平静。

 

总结
其实这个缓存清理的问题本身很简单,大家都懂,就和释放数据库连接等情况一样,需要放到finally块里面,
这个即使代码抛异常了也能正常释放或清理。但是就是撸这段代码的时候,因为这样那样的原因一时没有想到。
如果公司有代码review的环节的话会好很多,如果没有review,那么在写完代码后最好自己review一遍。
否则,万一出现类似的问题真的有点尴尬,正如题目所说“清缓存的姿势不对,真的会出生产bug哦”。
希望你我今后都能避免这种情况的发生。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120882.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql联合索引失效

    mysql联合索引失效联合索引,能够缩小查询范围的字段放在第一个,比如表sensor_coc_repay_feature存近一个月数据两千多万条,建立联合索引(time,distinct_id),按照查询select*fromsensor_coc_repay_featurewheredistinct_id=%sandtime>‘2022-02-20’,此时然后按照联合索引最左匹配有使用到了time,distinct_id,但是经过time查询后的数据还会是全表,mysql会认为该查询还不如走全表查询

    2025年9月3日
    11
  • 约瑟夫环问题详解

    约瑟夫环问题详解在牛客网上做到一道题,是约瑟夫环的变型,所以借此学习一下新知识,并且巩固一下对题目意思的理解,这一篇仅作约瑟夫环问题的解释,下一篇再写题目:1.首先,我们先来了解一下什么是约瑟夫环问题:讲一个比较有意思的故事:约瑟夫是犹太军队的一个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余人,他们都是宁死不屈的人,所以不愿投降做叛徒。一群人表决说要死,所以用一种策略来先后杀…

    2022年6月4日
    34
  • cefsharp设置cookie,CefSharp如何存储Cookie

    cefsharp设置cookie,CefSharp如何存储CookieIcan’tgetcookiestosaveinCefSharp.HereiswhatItried:CefSettingssettings=newCefSettings();stringpath=Environment.GetFolderPath(Environment.SpecialFolder.Desktop);Cef.Initialize(newCefS…

    2022年9月18日
    2
  • stringbuild和stringbuffer的区别_string和stringbuilder的区别

    stringbuild和stringbuffer的区别_string和stringbuilder的区别JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据.这个String类提供了数值不可改变的字符串.而这个StringBuffer类提供的字符串进行修改.当你知道字符数据要改变的时候你就可以使用 StringBuffer.典型地,你可以使用 StringBuffers来动态构造字符数据.一、String的使用方法:

    2022年9月21日
    3
  • 1.两数之和-Python-LeetCode

    1.两数之和-Python-LeetCode刚开始接触算法方面,好多都不懂,打算每刷一题就整理一下题目:给定一个整数数列,找出其中和为特定值的那两个数。你可以假设每个输入都只会有一种答案,同样的元素不能被重用。示例:给定nums=[2,7,11,15],target=9因为nums[0]+nums[1]=2+7=9所以返回[0,1]解法一:.刚开始看到的的时候,第一个想到的就是用一个嵌套循环把n…

    2022年6月8日
    26
  • Java线程池参数配置

    Java线程池参数配置在线程池的实际使用中,参数的配置总让人难以把握。在网上搜了一下,主要有以下的方案。跟大家分享。1.基本概念1.1ThreadPoolExecutor的重要参数corePoolSize:核心线程数核心线程会一直存活,及时没有任务需要执行 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭queueCapacity:任务队列容量(阻塞队列)当核心线程数达到最大时,

    2022年5月23日
    71

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号