概述
前言
在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。
为了克服上述的问题,项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。
redis技术就是NoSQL技术中的一种,但是引入redis又有可能出现缓存穿透,缓存击穿,缓存雪崩等问题。
原因
- 缓存穿透:缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
- 缓存击穿:缓存击穿,是指一个key非常热点,在不停的扛着大的并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
- 缓存雪崩:缓存雪崩,是指在某一个时间段,缓存集中过期失效。
缓存穿透解决方案
1、布隆过滤器
在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截,当收到一个对key请求时先用布隆过滤器验证是key否存在,如果存在在进入缓存层、存储层。可以使用bitmap做布隆过滤器。这种方法适用于数据命中不高、数据相对固定、实时性低的应用场景,代码维护较为复杂,但是缓存空间占用少。
布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
2、缓存空值
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个较短的过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题:
如果空值能够被缓存起来,这意味着缓存需要更多的空间存储和更多的键,因为这当中可能会有很多的空值的键;
即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿
1、设置热点永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。
但是会存在数据不一致的情况,同时代码复杂度会增大。
2、分布式互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获取分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
但是存在一定的隐患,如果在查询数据库 + 和 重建缓存时间过长,也可能会存在死锁和线程池阻塞的风险。但是这种方法能够较好地降低后端存储负载,并在一致性上做得比较好。
缓存雪崩
1、保证Redis的高可用
这个思想的含义是,既然redis有可能挂掉,那我就多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建redis集群。
2、数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
3、过期时间设置随机值
不同的key的过期时间不相同
4、限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
参考博文:https://blog.csdn.net/womenyiqilalala/article/details/105205532
参考博文:https://www.cnblogs.com/xichji/p/11286443.html
最后
以上就是悦耳水杯为你收集整理的Redis 缓存穿透、缓存击穿、缓存雪崩的原因 + 解决方案前言原因的全部内容,希望文章能够帮你解决Redis 缓存穿透、缓存击穿、缓存雪崩的原因 + 解决方案前言原因所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复