Hello , 大家好 , 这个专栏给大家带来的是 Redis 系列 ! 本篇文章给大家讲解的是 Redis 的缓存. 在 Redis 缓存系统中 , 缓存穿透、缓存击穿、缓存雪崩和缓存预热是常见的问题 , 它们对系统的性能和稳定性有着重要的影响 . 而缓存穿透、缓存击穿、缓存雪崩和缓存预热又是面试常考问题 , 所以大家一定要仔细认真的阅读 !
本专栏旨在为初学者提供一个全面的 Redis 学习路径,从基础概念到实际应用,帮助读者快速掌握 Redis 的使用和管理技巧。通过本专栏的学习,能够构建坚实的 Redis 知识基础,并能够在实际学习以及工作中灵活运用 Redis 解决问题 .
专栏地址 : Redis 入门实践
Redis 最主要的用途主要有三个方面 :
缓存的作用就是让我们能够更快地获取到数据 , 一般来说速度快的设备可以给速度慢的设备去做缓存 .
对于硬件的访问速度来说 , 通常情况下是这样的 : CPU 寄存器 > 内存 > 硬盘 > 网络
比较常见的是使用内存来去作为硬盘的缓存 (Redis) , 甚至我们也可以使用硬盘来去作为网络的缓存
使用硬盘来去作为网络的缓存这种场景也是存在的 , 比如 : 浏览器的缓存 , 浏览器通过 HTTP/HTTPS 从服务器上获取到数据 (HTML / CSS / JS / 图片 / 视频 / 音频 / 字体 …) 并且进行展示 , 那像这些体积大而且变化不频繁的数据就可以保存到浏览器本地 , 这就是使用硬盘来去给网络做缓存 .
在一个网站中 , 我们通常会使用 Redis 来去作为关系型数据库 (MySQL) 的缓存
为什么一般来说关系型数据库性能都不高 ?
- 关系型数据库把数据存储到硬盘上 , 但是硬盘的 IO 速度并不快 , 尤其是随机访问
- 如果查询不能命中索引 , 就需要进行表的整个遍历 , 这样就会大大增加硬盘的 IO 次数
- 关系型数据库对于 SQL 的执行会做一系列的解析、校验、优化工作
- 一些复杂查询 (比如 : 笛卡尔积操作) 效率也会降低
由于关系型数据库效率一般比较低 , 所以能够承担的并发量有限 . 一旦请求数量变多 , 数据库的压力就会变大 , 甚至严重到宕机 .
那如何提高 MySQL 能够承担的并发量呢 ?
如何知道 Redis 中应该存储哪些数据呢 ? 也就是如何知道哪些数据属于热点数据呢 ?
那我们需要先了解一下缓存的更新策略
首先我们会把访问的数据以日志的形式记录下来 .
通过日志 , 就可以把访问的数据记录下来 , 然后针对这些日志进行统计 , 按照一段时间内数据出现的频率进行降序排序 , 然后排名靠前的数据就可以认为是热点数据 .
那这个热点数据 , 就可以根据当前的统计维度 (每 天/周/月) 来定期更新 , 我们可以写一套离线的流程 (比如使用 Shell / Python … 来去写一些脚本代码) 来进行定时任务的触发 .
这种方式的优点是上述过程实现比较简单 , 过程更可控 , 方便排查问题
那缺点也很明显 , 它的实时性不够 , 如果出现一些突发事件 , 导致一些本来不是热词的内容变成了热词了
比如 : 春晚这个关键词 , 如果定期生成的话 , 假如周期是一个月 , 那年都过完了 , 春晚这个热搜才被统计出来
实时生成的策略是 :
但是这样不停地写 Redis , 就会使 Redis 的内存占用越来越多 , 从而逐渐的达到内存上限
此时如果继续插入数据 , 就会出现一些问题 , 为了解决上述情况 , Redis 就引入了一些内存淘汰策略
在 Redis 中有一个配置项 , 就可以设置 Redis 采取哪种内存淘汰策略
经过一段时间的动态平衡 , Redis 中的 key 就都逐渐成了热点数据了
我们之前了解过 , 缓存中的数据有两种更新策略
在 Redis 服务器首次接入之后 , Redis 服务器中是没有任何数据的 . 而实时生成的步骤是客户端先查询 Redis 的数据 , 如果没查到就再查一次 MySQL , 然后将查询到的数据也写入到 Redis 中 .
这样的话 , 在服务器刚启动的时候 , 所有的请求都会访问 MySQL , 就会给 MySQL 造成不小压力 . 随着时间的推移 , Redis 上面积累的数据越来越多 , MySQL 的压力就会越来越小 .
所以我们就需要在服务器刚启动的时候进行缓存预热 , 避免服务器刚启动的时候导致 MySQL 压力过大 .
缓存预热的步骤是将定期生成和实时生成相结合 , 通过离线的方式用一些统计途径 , 先把热点数据找到一批然后导入到 Redis 中 . 此时导入的这些热点数据就能够减轻 MySQL 很大压力了 , 随着时间的推移 , 逐渐就可以使用新的热点数据淘汰掉旧的数据了 .
缓存穿透指的是查询的某个 key , 他在 Redis 中查询不到 , 在 MySQL 中也查询不到 , 那这个 key 肯定也不会被更新到 Redis 中 .
那如果这样的数据存在很多并且还反复查询 , 一样也会给 MySQL 带来很大压力 .
一般来说 , 出现这样的情况主要有以下几个原因 :
我们通过改进业务 / 加强监控报警这些方法 , 虽然能够解决 , 不过是亡羊补牢 .
一般来说 , 主要采用的方案有以下几种 :
布隆过滤器本质上是结合了 hash + bitmap 这两种结构 , 以较小的空间开销和较快的时间速度 , 实现针对 key 是否存在的判定
缓存雪崩指的是由于在短时间内 , Redis 上大规模的 key 失效 , 导致缓存命中率陡然下降 , 导致 MySQL 压力迅速上升 , 甚至宕机 .
产生这种情况主要有以下几种原因 :
那解决的原因一般如下 :
缓存击穿的英文全称指的是 Cache breakdown , 其中 breakdown 更适合翻译成瘫痪
所以缓存击穿我们就可以理解为缓存瘫痪 , 他是缓存雪崩的特殊情况 , 针对热点 key , 突然过期了 , 这样就导致了大量的请求直接访问到数据库上 , 甚至引起数据库宕机 .
它的解决方案主要有以下几点 :
服务降级指的就是本身我们服务器的功能有 10 个 , 但是在一些特定情况下适当的关闭一些不重要的功能 , 只保留一些核心的功能 (超级省电模式 , 只保留了电话、短信、相机等核心功能)
文章到这里就结束喽 , 不知道你有没有被缓存预热、缓存穿透、缓存雪崩、缓存击穿绕蒙 , 如果对你有帮助的话 , 还请一键三连 , 你的鼓励是对我最大的认可~