昨天一位新朋友找我聊缓存穿透,他也背了八股文,但是还是被卡住了。
八股文式回答:
面试官:说说缓存穿透和解决方案
新朋友:缓存穿透就是请求来查询的数据不在数据库中,也不在缓存中。这样每次请求过来,都会去查数据库。如果出现大量类似的请求,可能会把我们的数据库给打垮。解决方案有:第一种是使用布隆过滤器,但是布隆过滤器存在误算率 。第二种缓存空结果,设置一个空对象,推荐使用第二种。
她觉得自己回答得还行,面试官也点头了。
可是,面试官又继续追问了,如果一个用户恶意请求,查询都是不存在的产品信息,这样岂不是会导致大量无用缓存吗?
她告诉我,当前就懵逼了

,看过的八股文里并没有这一条!
我们来看看缓存穿透的这个流程:

这位朋友采用常规背八股文的回答面试官,但是稍微再问点延伸性的问题,就不知所措了。
其实,我们可以对这些空对象设置一个有效期,这样也就是顶多是被恶意攻击时候,出现大量的空对象缓存。
我们对前面的流程图进行改进,请看下图:

写一个伪代码,你也可以回去找个场景练练手。
- //缓存空对象
- public static final String EMPTY_PRODUCT_CACHE = "{}";
-
- public Product getProductInfo(Long productId){
- Product product;
- //创建缓存key
- String productCacheKey = "PRODUCT_INFO_"+productId;
- //查询缓存
- String productCacheStr = redis.get(productCacheKey);
- //判断缓存是否存在
- if(!StringUtils.isEmpty(productCacheStr)){
- //判断是否为空对象
- if(EMPTY_PRODUCT_CACHE.equals(productCacheStr)){
- //继续续命
- redis.expire(productCacheKey,空对象有限期,时间单位);
- return null;
- }
- product = JSON.parseObject(productCacheKey, Product.class);
- //继续续命
- redis.expire(productCacheKey,产品有限期,时间单位);
- return product;
- }
-
- product = productDao.getProductInfoById(productId);
-
- if(product != null){
- //放入缓存
- redis.set(productCacheKey,JSON.toJSONGString(product),产品有限期,时间单位);
- }else{
- //缓存空对象
- redis.set(productCacheKey,EMPTY_PRODUCT_CACHE,空对象有限期,时间单位);
- }
-
- return product;
- }
以上就是这位小粉丝找我聊的问题,我也给他一些忠告,被八股文只能是一种抱佛脚的应付面试。如果想比别人有所同步,光被八股文还是不够的。就像之前,一个群友找我聊分布式锁,我给他的建议是先搞清楚为什么需要分布式锁?然后,再去搞清楚目前市面上有哪些实现方案,每一种方案实现原理是什么,还要清楚这些实现方案的优缺点。
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论
咱们下期见!答案获取方式:已赞 已评 已关~
学习更多JAVA知识与技巧,关注与私信博主(03)
