Redis缓存

什么是缓存?

缓存时计算机中的一个经典的概念,在很多场景中都能用到,核心思路就是把一些常用的数据放到触手可及(访问速度快)的地方,方便随时读取。

比如坐高铁刷身份证,身份证放在箱子里,但不能每次都打开箱子拿身份证,所以可以把身份证先放口袋里,虽然空间小,但访问速度快。此处口袋就是皮箱的缓存!

所以,缓存是更快,但空间上是不足的,因此大部分时候,缓存只放一些热点数据。

使用Redis作为缓存

在一个网站中,我们会经常用到关系型数据库,比如mysql来存储数据,但是关系型数据库虽然功能强大,但有一个很大缺陷,就是性能不高。

为什么说关系型数据库性能不⾼?
1. 数据库把数据存储在硬盘上, 硬盘的 IO 速度并不快. 尤其是随机访问.
2. 如果查询不能命中索引, 就需要进⾏表的遍历, 这就会⼤⼤增加硬盘 IO 次数.
3. 关系型数据库对于 SQL 的执⾏会做⼀系列的解析, 校验, 优化⼯作.
4. 如果是⼀些复杂查询, ⽐如联合查询, 需要进⾏笛卡尔积操作, 效率更是降低很多.
那如何能让数据库承担更大的并发量?核心思路有两个:
1.开源:引入更多机器,部署更多的数据库实例,构成数据库集群。
2.节流:引入缓存,使用其他的方式保存经常访问的热点数据,从而降低直接访问数据库的请求数量。
Redis就是一个用来作为数据库缓存的常见方案。
redis访问速度比mysql快很多,处理同一个访问请求,redis消耗的系统资源比MySQL少很多,所以redis能支持的并发量更大。
因为redis数据在内存中,访问内存比硬盘快很多;redis只是支持简单的key-value存储,不涉及复杂查询。
客⼾端访问业务服务器, 发起查询请求.
业务服务器先查询 Redis, 看想要的数据是否在 Redis 中存在.
   ◦ 如果已经在 Redis 中存在了, 就直接返回. 此时不必访问 MySQL 了.
   ◦ 如果在 Redis 中不存在, 再查询 MySQL

缓存的更新策略

1.定期生成

每隔⼀定的周期(⽐如⼀天/⼀周/⼀个⽉), 对于访问的数据频次进⾏统计. 挑选出访问频次最⾼的前 N%的数据。
这种做法实时性较低. 对于⼀些突然情况应对的并不好。

2.实时生成

先给缓存设定容量上限(可以通过 Redis 配置⽂件的 maxmemory 参数设定).
接下来把⽤⼾每次查询:
如果在 Redis 查到了, 就直接返回.
如果 Redis 中不存在, 就从数据库查, 把查到的结果同时也写⼊ Redis.
如果缓存已经满了(达到上限), 就触发缓存淘汰策略, 把⼀些 "相对不那么热⻔" 的数据淘汰掉.
按照上述过程, 持续⼀段时间之后 Redis 内部的数据⾃然就是 "热⻔数据" 了.
通⽤的淘汰策略主要有以下⼏种:
FIFO (First In First Out) 先进先出
把缓存中存在时间最久的 (也就是先来的数据) 淘汰掉.
LRU (Least Recently Used) 淘汰最久未使⽤的
记录每个 key 的最近访问时间. 把最近访问时间最⽼的 key 淘汰掉.
LFU (Least Frequently Used) 淘汰访问次数最少的
记录每个 key 最近⼀段时间的访问次数. 把访问次数最少的淘汰掉.
Random 随机淘汰
从所有的 key 中抽取幸运⼉被随机淘汰掉
这⾥的淘汰策略, 我们可以⾃⼰实现. 当然 Redis 也提供了内置的淘汰策略, 也可以供我们直接使⽤.
Redis 内置的淘汰策略如下:
•   volatile-lru 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中使⽤LRU(最近最
少使⽤)算法进⾏淘汰
•   allkeys-lru 当内存不⾜以容纳新写⼊数据时,从所有key中使⽤LRU(最近最少使⽤)算法进
⾏淘汰.
•   volatile-lfu 4.0版本新增,当内存不⾜以容纳新写⼊数据时,在过期的key中,使⽤LFU算法
进⾏删除key.
•   allkeys-lfu 4.0版本新增,当内存不⾜以容纳新写⼊数据时,从所有key中使⽤LFU算法进⾏
淘汰.
•   volatile-random 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中,随机淘汰数
据.
•   allkeys-random 当内存不⾜以容纳新写⼊数据时,从所有key中随机淘汰数据.
•   volatile-ttl 在设置了过期时间的key中,根据过期时间进⾏淘汰,越早过期的优先被淘汰.
(相当于 FIFO, 只不过是局限于过期的 key)
•   noeviction 默认策略,当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错.

缓存预热

使⽤ Redis 作为 MySQL 的缓存的时候, 当 Redis 刚刚启动, 或者 Redis ⼤批 key 失效之后, 此时由于Redis ⾃⾝相当于是空着的, 没啥缓存数据, 那么 MySQL 就可能直接被访问到, 从⽽造成较⼤的压⼒.因此就需要提前把热点数据准备好, 直接写⼊到 Redis 中. 使 Redis 可以尽快为 MySQL 撑起保护伞.
热点数据可以基于之前介绍的统计的⽅式⽣成即可. 这份热点数据不⼀定⾮得那么 "准确", 只要能帮助MySQL 抵挡⼤部分请求即可. 随着程序运⾏的推移, 缓存的热点数据会逐渐⾃动调整, 来更适应当前情况.

缓存穿透

什么是缓存穿透?
访问的 key 在 Redis 和 数据库中都不存在. 此时这样的 key 不会被放到缓存上, 后续如果仍然在访问该key, 依然会访问到数据库.
这就会导致数据库承担的请求太多, 压⼒很⼤.
这种情况称为 缓存穿透.
为何产⽣?
原因可能有⼏种:
业务设计不合理. ⽐如缺少必要的参数校验环节, 导致⾮法的 key 也被进⾏查询了.
开发/运维误操作. 不⼩⼼把部分数据从数据库上误删了.
⿊客恶意攻击.
如何解决?
针对要查询的参数进⾏严格的合法性校验. ⽐如要查询的 key 是⽤⼾的⼿机号, 那么就需要校验当前key 是否满⾜⼀个合法的⼿机号的格式.
针对数据库上也不存在的 key , 也存储到 Redis 中, ⽐如 value 就随便设成⼀个 "". 避免后续频繁访问数据库.
使⽤布隆过滤器先判定 key 是否存在, 再真正查询.

缓存雪崩

什么是缓存雪崩?
短时间内⼤量的 key 在缓存上失效, 导致数据库压⼒骤增, 甚⾄直接宕机.
本来 Redis 是 MySQL 的⼀个护盾, 帮 MySQL 抵挡了很多外部的压⼒. ⼀旦护盾突然失效了, MySQL⾃⾝承担的压⼒骤增, 就可能直接崩溃.
为何产⽣?
⼤规模 key 失效, 可能性主要有两种:
Redis 挂了.
Redis 上的⼤量的 key 同时过期.
为啥会出现⼤量的 key 同时过期?
这种和可能是短时间内在 Redis 上缓存了⼤量的 key, 并且设定了相同的过期时间.
如何解决?
部署⾼可⽤的 Redis 集群, 并且完善监控报警体系.
不给 key 设置过期时间 或者 设置过期时间的时候添加随机时间因⼦

缓存击穿

什么是缓存击穿?

相当于缓存雪崩的特殊情况. 针对热点 key , 突然过期了, 导致⼤量的请求直接访问到数据库上, 甚⾄引 起数据库宕机.

如何解决?
基于统计的⽅式发现热点 key, 并设置永不过期.
进⾏必要的服务降级. 例如访问数据库的时候使⽤分布式锁, 限制同时请求数据库的并发数.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值