redis-缓存穿透和缓存击穿和缓存雪崩
关于使用redis 作为缓存,我们需要考虑以下问题
缓存穿透
缓存穿透的定义为当存在大量请求的情况下,请求会首先查询redis,redis中不存在数据,此时需要查询DB判断数据是否存在,对于DB返回的结果也是数据不存在的情况;
在这种情况下由于数据确实不存在,从而导致 一次请求 会连续请求到 redis 以及 db ,从而导致 redis 和 db 的负载骤增,且当前情况属于无意义的(短时间内数据不会存在),导致机器性能浪费;
解决方案(两种操作):
- 对于db中不存在的数据,在通过redis穿透到db查询一次后,在redis中对当前请求的key写入一个自定义空结构体对象(非null),对于该情况就可以保证对于db中不存在的数据只会查询一次db,后续所有的请求由于在redis中key存在,因此降低了db的压力,避免了db的资源浪费(特别时针对未命中索引导致全表扫描的情况);
- 利用布隆过滤器的特点,其特征为对于布隆过滤器判定不存在的数据,则肯定不存在;对于布隆过滤器判定为存在的数据,实际查询可能不存在,对于当前情况发生的原因为布隆过滤器hash冲突问题导致的;
- 布隆过滤器是基于位图结构的数据存储结构,其核心是基于hashtable,通过多个hash计算定位避免了数组空洞,节省了空间;但由于布隆过滤器使用hash计算但并不能绝对避免hash冲突的发生;
- 对于hash冲突产生的原因可能就是因为存储的数据量过大,导致数组可用空间减少(当前是表现不是原因),因此我们需要对剩余空间设置一个阈值,当剩余空间小于当前阈值时,就需要对数组进行自动扩容;
- 通过降低布隆过滤器的误判率,从而降低服务(db/redis)的压力
- 可以通过在redis中维护一个布隆过滤器所需要的数据,另外一个维护真实缓存到redis中的数据,其核心就是利用空间换时间,对于布隆过滤器判定为存在的数据,只需要再查询一次redis判断数据是否真的的存在;
- 关于误判率可以通过在redis中维护一个计数器来统计误判率,当误判率达到一定阈值后,就需要对布隆过滤器进行扩容,从而降低其hash冲突概率
warning : 对于以上两种方案都需要考虑缓存一致性问题,即当db中写入新的数据时,需要保证redis中也要将数据进行同步
缓存击穿
缓存击穿和缓存穿透的区别点在于 缓存击穿 只针对redis中不存在数据,而db中存在数据,只是在大并发情况下访问热点数据时,redis数据突然失效导致,大量的并发请求访问到db,导致db压力骤增;
解决方案(两种解决方案)
- 热点数据永不过期,一个是设置存活时间长,另外使用异步线程来探测热点数据剩余存活时间,针对快过期的数据,重新从数据库读取并延长存活时间
- 对于热点数据当发现redis中不存在数据时,对需要请求db的操作进行加锁操作,并开启双重校验(在获取锁成功后,再次读取redis,主要是为了保证不会重复读取数据库,只需要读取一次即可),当从db读取到数据后,并将数据写入到redis缓存中;保证后续被阻塞的读取请求都可以从redis中读取到数据
缓存雪崩
缓存雪崩的定义为 在同一时间内存在大量缓存同时失效,当此时如果存在大量请求,导致的结果就是db压力骤增,从而有可能导致服务崩溃
解决方案
- 通过维护一个基准缓存有效期并搭配一个优先的随机值,从而避免存在大量的redis key失效时间相同
- 对于热点数据(redis 中 key访问频率较高,且真实存在的数据),可以通过自动延长key存活时间

浙公网安备 33010602011771号