2024.1.29 关于 Redis 缓存详解

目录

缓存基本概念

二八定律

Redis 作为缓存

缓存更新策略

定期生成

实时生成

内存淘汰策略

缓存使用的注意事项

关于缓存预热

关于缓存穿透

关于缓存雪崩

关于缓存击穿(瘫痪)


缓存基本概念

  • 所谓缓存,其实就是将一部分常用数据放到访问速度更快的地方,方便随时读取

实例理解

  • 硬件的访问速度一般为:CPU 寄存器 > 内存 > 硬盘 > 网络
  • 此时最常见的 便是使用 内存 作为 硬盘 的缓存,即 Redis 定位
  • 当然,硬盘 也能作为 网络 的缓存!因为硬盘的访问速度相对网络来说更快!
  • 比如 浏览器缓存
  • 浏览器通过 http/https 从服务器上获取数据(html、css、js、图片、视频、音频、字体 等)并进行展示
  • 像 图片、视频、音频等 这些体积大 又不太会改变的数据就可以保存到浏览器本地,即浏览器所在主机的硬盘上
  • 等到后续再打开该网页时,就不必重新从网络获取上述数据了!

二八定律

  • 指 20% 的数据,可以应对 80% 的请求

注意:

  • 缓存虽然速度快,但空间小
  • 大部分情况下,缓存仅存放一些热点数据即可,因为这些热点数据足以应对大多数场景

Redis 作为缓存

  • 我们通常使用 Redis 作为数据库(MySQL)的缓存

注意:

  • 数据库是十分重要的组件,即绝大部分商业项目均会涉及
  • 但 MySQL 的访问速度又相对较慢,因此我们便可使用 Redis 来作为 MySQL 的缓存

问题:

  • 为什么说关系型数据库性能不高?

回答:

  1. 数据库把数据存储在硬盘上,但硬盘的 IO 速度并不快,尤其是随机访问
  2. 如果查询不能命中索引,便需进行表的遍历,这就会大大增加硬盘的 IO 次数
  3. 关系型数据库对应 SQL 的执行会做一系列的解析、校验、优化工作
  4. 如果是一些复杂查询,如联合查询,需要进行笛卡尔积操作,效率更是降低很多

注意:

  • 因为 MySQL 等数据库,效率相对较低,所以承担的并发量有限,一旦请求量多了,数据库的压力就会很大,甚至于很容易便宕机了
  • 服务器每处理一个请求,都需消耗一些硬件资源(CPU、内存、硬盘、网络 等)
  • 任意一种资源的消耗超出了机器所能提供的上限,此时机器便会很容易出现故障

问题:

  • 如何提高 MySQL 所能承担的并发量?(客观需求)

回答:

  1. 开源:引入更多的机器,构成数据库集群
  2. 节流:引入缓存,将一些频繁读取的热点数据,保存到缓存上,后续在查询数据时,如果缓存中已存在,便不再访问 MySQL,直接从缓存中拿数据即可(典型的方案)

缓存更新策略

  • 此处我们解决关于 如何知道 Redis 中应存储哪些数据,即哪些数据为 热点数据?

定期生成

  • 将访问数据,以日志形式给记录下来
  • 通过日志,将都使用到了哪些词给记录下来,此时便可以针对这些日志信息进行统计了
  • 统计这 一天/一周/一个月 每个词出现的频率,再根据频率降序排序
  • 再取出前 20% 的词,就可以认定这些词为 热点词
  • 接下来就可以将这些热点词 所涉及到的搜索结果给提前拎出来,并放到类似于 Redis 这样的缓存中了

注意点一:

  • 当然上述所讲的数据量是非常大的,所以我们可以写个程序来进行统计
  • 数据量可能大到说 一台机器都存不下
  • 此时便需要使用分布式的系统来存储这些日志(HDFS)
  • 再使用 hadoop 的 map-reduce 来写代码进行统计
  • 也可基于 HDFS 的 HBASE 这样的数据库来写 sql 统计
  • 这属于 大数据工程师 的日常工作

注意点二:

  • 此处的数据可以根据当前这里的统计纬度,来定期更新
  • 按照天级别统计的,就每天更新一次
  • 按照月级别统计的,就每个月更新一次
  • 写一套离线的流程(往往使用 shell,python 写脚本代码)
  • 然后通过 定时任务 的形式来触发

定时任务的内容包括:

  1. 完成统计热词的过程
  2. 根据热词,找到搜索结果的数据
  3. 将得到的缓存数据同步到缓存服务器上
  4. 控制这些缓存服务区自动重启

优点:

  • 上述过程,实际上实现起来还是比较简单的
  • 其过程更可控,缓存中的数据大多都比较固定,方便排查问题

缺点:

  • 实时性不够,如果出现一些突发性事件,有一些本来不是热词的内容成了热词
  • 此时新的热词就可能给后面的数据库啥的代码较大的压力
  • 比如 春节晚会 这个突发性热词

实时生成

  • 如果在 Redis 中查到了,就直接返回
  • 如果在 Redis 中查不到,就从数据库查,并将查到的结果同时写入 Redis  
  • 这样不停的写 Redis,就会使 Redis 的内存占用越来越多
  • 逐渐达到内存上限,此处的内存上限可通过配置 maxmemory 参数设定,即不一定指的是机器内存上限,Redis 中可通过配置设定最多使用多少内存
  • 达到内存上限后,再继续往 Redis 中插入数据的话,便会触发内存不够问题!
  • 而为了解决改问题,Redis 便引入了 内存淘汰策略
  • 通过内存淘汰策略,并经过一段时间的动态平衡,Redis 中的 key 将逐渐变为热点数据


内存淘汰策略

  • FIFO【先进先出】:将内存中存在时间最久的(也就是先来的数据)给淘汰掉
  • LRU【淘汰最久未使用的】:记录每个 key 的最近访问时间,将最近访问时间最老的 key 给淘汰掉
  • LFU【淘汰访问次数最少的】:记录每个 key 最近一段时间的访问次数,将访问次数最少的 key 给淘汰掉(相对靠谱
  • Random【随机淘汰】:从所有的 key 中抽取幸运儿被随机淘汰掉(不太合理)

注意:

  • 当然具体采取哪种策略,还需结合实际场景来具体问题具体分析
  • Redis 中有一个配置项,可以设置 Redis 采取上述哪种策略淘汰内存数据

缓存使用的注意事项

关于缓存预热

  • 当 Redis 服务器首次接入时,服务器中是没有数据的
  • 客户端先查询 Redis,如果没有查到,则再查 MySQL
  • 查到了之后,便会将数据给写入到 Redis 中
  • 针对上述情况,此时所有请求均会打给 MySQL
  • 并随着时间的推移,Redis 上的数据也越积越多
  • 自然 MySQL 所承担的压力也就越来越小了

解决方案:

  • 缓存预热 就是用来解决上述问题的
  • 此处我们可以将 定期生成 和 实时生成 给结合起来
  • 先通过离线的方式,根据统计,先找到一批热点数据,并将其导入到 Redis 中
  • 此时导入的这批热点数据,就能帮 MySQL 承担很大一部分压力了
  • 最后随着时间的推移,逐渐使用新的热点数据淘汰旧的热点数据

注意:

  • 定期生成 是不涉及预热的,仅实时生成涉及该问题

关于缓存穿透

  • 查询某个 key 时,Redis 和 MySQL 中均没有
  • 便可能导致 这次查询 ——> 没有,下次查询 ——> 仍然没有  的情况
  • 如果存在很多像这样的 key,并且还反复查询,一样也会给 MySQL 带来很大的压力

产生原因:

  1. 业务设计不合理,如缺少必要的参数校验环节,导致非法 key 也被运行查询(典型)
  2. 开发 或 运维误操作,不小心将部分数据从数据库上误删了(没那么典型,表现也是缓存穿透,误删操作,不一定能即时发现)
  3. 黑客恶意攻击(比较少见)

不靠谱的解决方案:

  • 通过改进业务 或 加强监控报警(亡羊补牢)
  • 事故出现之后,才采取行动!

靠谱的解决方案:(减低问题的严重性)

  1. 如果发现该 key 在 Redis  和 MySQL 上均不存在,此时直接将 key 写入 Redis 中,并将其 value 设成一个非法值(如 " ")
  2. 引入 布隆过滤器,将所有的 key 均插入到 布隆过滤器 中,每次查询 Redis 或 MySQL 前都先判定一下该 key 是否在存在于 布隆过滤器 上

具体解释:

  • 布隆过滤器,本质上结合了 哈希 与 位图 ,以比较小的空间开销,比较快的时间速度,实现针对 key 是否存在的判定

关于缓存雪崩

  • 短时间内,Redis 上大规模的 key 失效,导致缓存命中率陡然下降,进而导致 MySQL 的压力迅速上升,甚至直接宕机

产生原因:

  1. Redis 直接挂了(Redis 宕机 或 Redis 集群模式下大量节点宕机)
  2. Redis 虽正常运行,但可能由于之前短时间内设置了很多 key 给 Redis,且设置的过期时间均在同一时刻过期

注意:

  • 给 Redis 里设置 key 作为缓存时,有时候为了考虑缓存的时效性,便会设置过期时间(Redis 内存淘汰机制 配合着使用)

解决方案:

  1. 加强监控报警,加强 Redis 集群可用性的保证(集群监控、哨兵监控)
  2. 不给 key 设置过期时间 或 设置过期时间时通过添加随机因子来避免同一时刻过期

关于缓存击穿(瘫痪)

  • 相当于缓存雪崩的特殊情况
  • 此处是针对热点 key 突然过期,进而导致大量的请求直接访问到 MySQL 上,甚至直接引起数据库宕机

注意:

  • 热点 key 访问频率更高,影响更大

解决方案:

  1. 基于统计的方式筛选出热点 key ,并设置永不过期
  2. 进行必要的服务降级

理解服务降级:

  • 例如访问 MySQL 时,使用分布式锁,限制同时请求数据库的并发量
  • 例如本身服务器的功能有十个,但在特定情况下,可适当关闭一些不重要的功能,只保留核心功能(省电模式)
  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茂大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值