您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

快速了解缓存穿透与缓存雪崩

时间:2021-04-12 10:19:23  来源:微信公众号  作者:全菜工程师小辉

更多内容,欢迎关注微信公众号:全菜工程师小辉~

缓存穿透

缓存系统,一般流程都是按照key去查询缓存,如果不存在对应的value,就去后端系统(例如:持久层数据库)查找。如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力,这就叫做缓存穿透。

正常请求:

快速了解缓存穿透与缓存雪崩

 

正常请求

缓存击穿时:

快速了解缓存穿透与缓存雪崩

 

缓存击穿

如何避免

1. 缓存空结果

对查询结果为空的情况进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

2. 布隆过滤器

采用布隆过滤器,guava有实现api,或者使用redis的bitmap。将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。布隆过滤器对于固定的数据可以起到很好的效果,但是对于频繁更新的数据,布隆过滤器的构建会面临很多问题。另外布隆过滤器是有判断误差的,网上有很多详细的介绍,请读者自行搜索即可。

快速了解缓存穿透与缓存雪崩

 

布隆过滤器

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

如何避免

1. 互斥锁

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

快速了解缓存穿透与缓存雪崩

 

互斥锁

如果是单机,可以用synchronized或者lock来处理,如果是分布式环境就需要使用分布式锁。

使用互斥锁,代码如下,仅适用redis2.6.1以后支持setnx的版本。在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用redis的setnx操作去set一个mutex key。当操作返回成功时,再进行load db的操作并回设缓存,否则,就重试整个get缓存的方法。

快速了解缓存穿透与缓存雪崩

 

互斥锁

public String get(key) {
 List<String> resultList = (List<String>)redisTemplate.opsForValue().get(key);
 if(CollectionUtils.isEmpty(resultList)){
 final String mutexKey = key + "_lock";
 boolean isLock = (Boolean) redisTemplate.execute(new RedisCallback() {
 @Override
 public Object doInRedis(RedisConnection connection) throws DataAccessException {
 //只在键key不存在的情况下,将键key的值设置为value,若键key已经存在,则 SETNX 命令不做任何动作
 //命令在设置成功时返回 1 , 设置失败时返回 0
 return connection.setNX(mutexKey.getBytes(),"1".getBytes());
 }
 });
 if(isLock){
 //设置成1秒过期
 redisTemplate.expire(mutexKey, 1000, TimeUnit.MILLISECONDS);
 resultList = getValueBySql(key);
 redisTemplate.opsForValue().set(key, resultList, 1000, TimeUnit.SECONDS);
 redisTemplate.delete(mutexKey);
 }else{
 //线程休息50毫秒后重试
 Thread.sleep(50);
 retryCount--;
 System.out.println("=====进行重试,当前次数:" + retryCount);
 if(retryCount == 0){
 System.out.println("====这里发邮件或者记录下获取不到数据的日志,并为key设置一个空置防止重复获取");
 List<String> list = Lists.newArrayList("no find");
 redisTemplate.opsForValue().set(key, list, 1000, TimeUnit.SECONDS);
 return list;
 }
 return getCacheSave2(key,retryCount);
 }
 }
 return resultList;
}

2. 设置随机过期时间

不同的key,设置不同的过期时间,让缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低。

3. 设置二级缓存

做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

4. “永远不过期”

“永远不过期”包含两层意思:

  1. 从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。
  2. 从功能上看,把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期。

 

快速了解缓存穿透与缓存雪崩

 

“永远不过期”

这种方法对于性能非常友好,唯一不足的就是构建缓存时候,其余线程(非构建缓存的线程)可能访问的是老数据,但是对于一般的互联网功能来说这个还是可以忍受。

缓存预热

有效应对缓存的击穿和雪崩的一种方式是缓存预热。

缓存预热就是系统上线前,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。

解决思路

  1. 直接写个缓存刷新页面,上线时手工操作下。
  2. 数据量不大,可以在项目启动的时候自动进行加载。
  3. 定时刷新缓存。

限流

有效应对缓存的击穿和雪崩的另一种方式是限流。

在缓存失效后,通过队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

常见的限流算法

  1. 固定时间窗口算法(计数器)
  2. 滑动时间窗口算法
  3. 令牌桶算法
  4. 漏桶算法

有关限流算法的详细介绍,请点击查看高并发系统的限流算法与实现

总结

缓存穿透、击穿和雪崩是以预防为主、补救为辅,而在应对缓存的问题其实也没有一个完全完美的方案,只有最适合自己业务系统的方案。

更多内容,欢迎关注微信公众号:全菜工程师小辉~



Tags:缓存穿透   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
当查询Redis中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶意攻击时,接口的访问全部透过Redis访问数据库,而数据库中也没有这些数据...【详细内容】
2021-07-30  Tags: 缓存穿透  点击:(90)  评论:(0)  加入收藏
更多内容,欢迎关注微信公众号:全菜工程师小辉~缓存穿透缓存系统,一般流程都是按照key去查询缓存,如果不存在对应的value,就去后端系统(例如:持久层数据库)查找。如果key对应的value...【详细内容】
2021-04-12  Tags: 缓存穿透  点击:(310)  评论:(0)  加入收藏
对于缓存,大家肯定都不陌生,不管是前端还是服务端开发,缓存几乎都是必不可少的优化方式之一。在实际生产环境中,缓存的使用规范也是一直备受重视的,如果使用的不好,很容易就遇到缓...【详细内容】
2020-12-14  Tags: 缓存穿透  点击:(96)  评论:(0)  加入收藏
作为一个内存数据库,redis也总是免不了有各种各样的问题,这篇文章主要是针对其中两个问题进行讲解:缓存穿透和缓存雪崩。并给出一些解决方案。这两个问题是基本问题也是面试常...【详细内容】
2020-03-14  Tags: 缓存穿透  点击:(75)  评论:(0)  加入收藏
在现在互联网架构中,几乎每个互联网项目都会引入缓存系统,比如 Redis、Memcached。来保护下游数据库和提升系统并发量。不管使用哪种缓存系统都有可能遇到 缓存穿透 的问题。...【详细内容】
2020-03-10  Tags: 缓存穿透  点击:(64)  评论:(0)  加入收藏
1为什么需要缓存 如果没有缓存,那么所有业务请求会直接指向数据库,以MySQL为例的数据库基本都是基于磁盘的,而磁盘I/O开销大,面对大规模请求时,会降低系统性能。 对一些热点数据,...【详细内容】
2019-11-12  Tags: 缓存穿透  点击:(87)  评论:(0)  加入收藏
本篇文章主要谈谈Redis中很容易出现的三大问题现象:缓存击穿、缓存穿透以及缓存雪崩。不过在介绍这三个问题现象之前,我们首先需要先来了解下Redis中key的过期淘汰机制。众所...【详细内容】
2019-10-12  Tags: 缓存穿透  点击:(111)  评论:(0)  加入收藏
一、缓存穿透1.何为缓存穿透?缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查...【详细内容】
2019-09-23  Tags: 缓存穿透  点击:(166)  评论:(0)  加入收藏
01前言在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如...【详细内容】
2019-08-26  Tags: 缓存穿透  点击:(198)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条