Redis:key过期策略、缓存穿透、缓存击穿、缓存雪崩
key的过期策略
Redis 使用 惰性删除 + 定期删除
redis 数据库由dict
和expires
两个字典组成
- dict 负责存储所有的键值对
- expires 负责存储键的过期时间
Redis中可以对键设置过期时间,key过期后,Redis是如何处理的?
- redis提供了三种方式:立即删除、惰性删除、定时删除
1.立即删除
给key设置过期时间时,创建回调函数,当key有效期结束后立即执行回调函数,删除键释放内存。
缺点:删除操作会占用cpu时间,影响redis性能。
2.惰性删除
一个key过期后,不会立刻删除,等到下一次使用这个key时,检测到过期,此时才删除它。
缺点:若键过期了,一直没有被再次使用,会浪费内存(dict和expires字典中都要保存key-value的信息)。
3.定时删除
每隔一段时间,对存储键过期时间的expires字典进行检查,随机选取一些key检查过期就删除。
缓存的处理流程
- 前端发送请求,请求先到达redis,在redis缓存中查询是否有该数据,有就返回,没有就去数据库中查询。
- 在数据库中查询,数据库中有数据,同步到redis缓存,同时返回给前端。没有数据返回空。
缓存穿透
穿透的原因
请求的数据在redis缓存中不存在,数据库中也没有该数据,请求每次直接穿透打在数据库中。
例:查询数据库中id为-1
的数据,每次都会穿透redis访问数据库,大量恶意请求可能导致数据库挂掉。
总结:缓存和数据库中都没有该数据。
如何解决穿透?
- 将空对象返回给前端,并将空对象同步到缓存中。(给空对象设置较短的过期时间)
- 检验参数的合法性,不合法直接return
- 使用布隆过滤器
缓存击穿
击穿的原因
大量请求访问热点key,若key到期失效了,此时大量的请求直接到达数据库,可能导致数据库挂掉。
如何解决击穿?
- 设置key永久有效
- 这种情况是多个线程同时到达数据库查询该数据。可以给第一个请求的线程上锁。
- 在第一个请求的线程上加互斥锁,其他线程等着
- 持有锁的第一个线程查询到了数据,将数据同步到redis缓存
- 后面的线程在redis中查询到了数据,就不会到达数据库发生击穿了
缓存雪崩
雪崩的原因
在高并发下,大量redis缓存在同一时间失效到期或redis故障,所有的请求都会到达数据库,可能导致数据库挂掉。
如何解决雪崩?
- 不设置过期时间,默认永久有效,就不会发生雪崩了,但是浪费内存。
- 既然是同一时间失效导致的雪崩,我们随机初始key的过期时间,避免大量Key同时过期。
- 如果redis集群,将热点key平均分布到不同的redis结点上去,避免集体失效。
- 定时任务,在缓存失效前将缓存重新跑进去。
总结:
缓存穿透是缓存和数据库中都没有数据,一直查询数据库
缓存击穿是热点key突然失效,大量请求到达数据库
缓存雪崩是大面积(大量)key同时失效,大量请求到达数据库
如何避免redis宕机,请求全到达数据库的情况?
- 未宕机 :redis的高可用性(主从复制+哨兵机制),避免redis挂掉
- 已宕机 :redis宕机,设置本地缓存(ehcahe + 限流),避免请求全走数据库
- 宕机后 :redis持久化,重启后将数据从磁盘中加载到内存中来
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15582.html