当前位置: 首页 > news >正文

redis入门到精通系列(十一):redis的缓存穿透、缓存击穿以及缓存雪崩详解

欢迎关注同名微信公众号《Java鱼仔》,我们一起冲大厂

(一)缓存穿透(查不到)

1.1 概念

当用户想要查询一个数据的时候,发现redis内存数据库中没有,于是向持久化数据库查询发现也没有,相当于请求绕过缓存直接打到持久层。当用户很多的时候,如果大量缓存都没有命中,于是都去请求了持久化数据库,这会给持久化数据库带来很大的压力,这就是缓存穿透。

1.2 解决方案

缓存空对象
如果用户的请求在持久层中也未命中,即使返回的空对象也会将其缓存起来,并且设置一个过滤时间,之后再访问这个数据时缓存中就有了,保护了后端的数据库。
可能会导致的问题
1.如果空值能被缓存起来,就意味着我们需要更多的空间去储存很多数据库中为空的键。
2.对于缓存起来的空值我们会设置一个过期时间,这就会导致缓存层和存储层一段时间的数据不一致,比如原来为空值的键被放进了缓存,在未过期的时候数据库刚好新增了这样一个键,这对需要保持一致性的业务会有影响。

布隆过滤器
布隆过滤器可以理解为是一个不怎么精确的set,可以使用contains判断去判断这个值是否在布隆过滤器中存在。并且在达到去重的效果同时,可以节约大量的空间。因此我们可以将所有存在的值放入布隆过滤器中,请求首先进入过滤器,如果过滤器返回不存在,就直接驳回这个请求。因此这个请求就不会穿透到持久层的数据库中。
不过我也提到了,这是一个不怎么精确的数据结构,打个比方,对于一个key,如果布隆过滤器返回不存在,那么这个key在布隆过滤器中一定不存在,但是如果布隆过滤器返回key存在,那么有可能这个值在布隆过滤器中是不存在的。这点误差对于解决缓存穿透问题是完全可以接受的,毕竟布隆过滤器只是放在真实缓存前的一道屏障,只要对存在于缓存中的key不错误过滤就行。
对于布隆过滤器,我会在下一章进行讲解。

(二)缓存击穿(量太大、缓存过期)

2.1 概念

缓存击穿是指一个key非常热门,会有大量并发对这个点进行访问,在这个key失效的瞬间,持续的大并发就会穿过环境直接请求数据库,就好像在墙上打了一颗子弹一样。

2.2 解决方案

1.设置热点数据永不过期
从缓存层面上看,没有设置过期时间,就不会出现热点key过期后产生的问题
2.加互斥锁
使用分布式锁,使得对于每个key只有一个线程去查询后端的服务,这种方式可以将高并发的压力转移到分布式锁,因此对于分布式锁也是另外一个考验。

(三)缓存雪崩

3.1 概念

缓存雪崩指的是在某个时间端,缓存集中过期失效,大量请求直接打到持久层数据库。或者更加严重的情况缓存服务器直接宕机,所有请求直接打到持久层数据库,导致瞬间压垮持久层数据库。

3.2 解决方案

redis高可用
对于redis缓存服务器宕机导致的缓存雪崩,可以多增加几台redis服务器组成redis集群环境,实现redis的高可用。
限流降级
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,比如对于某个key只允许一个线程查询和写缓存,其他线程等待。
数据预热
数据预热是指在正式部署之前,把可能的数据预先加载到缓存中,对于不同的key设置不同的过期时间,让缓存失效的时间点尽量均匀。

相关文章:

  • 子数组最大值设计02
  • redis入门到精通系列(十二):看完这一篇文章别再说不懂布隆过滤器
  • 如何用SpringBoot(2.3.3版本)快速搭建一个项目?文末有小彩蛋
  • Linux上find命令详解
  • 一步步带你看SpringBoot(2.3.3版本)自动装配原理
  • CCF系列之I’m stuck!(201312-5)
  • SpringBoot配置文件及自动配置原理详解,这应该是SpringBoot最大的优势了吧
  • SpringBoot整合jdbc、durid、mybatis详解,数据库的连接就是这么简单
  • Git学习笔记(一)--- Git的安装与配置
  • SpringBoot整合SpringSecurity详解,认证授权从未如此简单
  • SpringBoot整合Shiro详解,还在自己写登陆注册早落伍了
  • [android] 请求码和结果码的作用
  • final 在 java 中有什么作用?
  • String str=“i”与 String str=new String(“i”)一样吗?
  • ajaxStart()和ajaxStop()方法
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Android组件 - 收藏集 - 掘金
  • C++类中的特殊成员函数
  • JS变量作用域
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Python语法速览与机器学习开发环境搭建
  • unity如何实现一个固定宽度的orthagraphic相机
  • 从0实现一个tiny react(三)生命周期
  • 多线程 start 和 run 方法到底有什么区别?
  • 解析带emoji和链接的聊天系统消息
  • 今年的LC3大会没了?
  • 老板让我十分钟上手nx-admin
  • 目录与文件属性:编写ls
  • 三分钟教你同步 Visual Studio Code 设置
  • 想写好前端,先练好内功
  • 做一名精致的JavaScripter 01:JavaScript简介
  • gunicorn工作原理
  • #HarmonyOS:Web组件的使用
  • #includecmath
  • #数学建模# 线性规划问题的Matlab求解
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (二)Linux——Linux常用指令
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (六)软件测试分工
  • (算法)Travel Information Center
  • (算法设计与分析)第一章算法概述-习题
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .NET Core 项目指定SDK版本
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 的字符串暂存池
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析
  • [BZOJ4016][FJOI2014]最短路径树问题
  • [C/C++随笔] char与unsigned char区别
  • [C++]命名空间等——喵喵要吃C嘎嘎
  • [C++数据结构](31)哈夫曼树,哈夫曼编码与解码