Spring缓存穿透问题修复

 本文来自网易云社区

 

本剧情纯属真实,犹如雷同实乃缘分。

 

发生

 

事情的发生在某天早上,天气怎样反正是忘了,只记得当时监控平台大量的数据库错误报警。 作为后端开发,当看到日志中大量的db连接获取失败,心情是复杂的。

看了下配置和实际连接数,竟然。。。没满。恩,可能是突发流量。然而没多久,一大波报警又袭来,感觉事情没那么简单。

常规措施无果,连续数次如此,看日志发现时间有点奇怪,都是间隔5分钟, 难道。。。缓存失效了? 看业务代码和缓存配置,很有可能。

 

业务代码表示

@Cacheable(value = "item_volume", key = "'item_' + #gid", unless = "#result == null")     public Item queryiItem(long gid) {         Optional<Item> optional = itemService.getItem(null, gid);         return optional.orNull();     } 

注: cache的实现用的是spring->

 

初步分析

 

没错,换配置item_volume过期时间5分钟,也就是说,当缓存过期后,此时如果有大量请求,那么这些请求都会因为缓存失效而请求数据库。 看起来情形是这样的:

 

 

 

如果假设成立,那就是spring在处理缓存的时候,如果没有命中,直接穿透执行实际操作(db查询),也就是说,中间是不加锁的。

这样就解释通了,但这是bug吗,还是spring认为是个feature, 这是个问题。

 

发展

 

Talk is cheap, show me the code. --linux之爹

关键是,code在哪。又得上套路了:套路: 既然是AOP,找找Advice。最直接能想到,就是在spring中找所有Advice接口的继承树,然而数量太多,逐个寻找验证实在是耗时。

熟悉spring事务的同学应该能想到@Transactional的Advice是TransactionInterceptor,那么cache是否对应对一个CacheInterceptor呢。一看,还真有,那就好办了,而且看起就是要找的。

 

修改代码

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信