REDIS缓存穿透,缓存击穿,缓存雪崩

REDIS缓存穿透,缓存击穿缓存雪崩原因+解决方案

缓存穿透:程序绕过缓存,不停的查询数据库

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

举例子:查询id=-1 这条数据库不存在的记录,缓存因为返回数据为空,所以不缓存,导致一直查数据。

方案1: 数据库返回空,也缓存一个空记录

方案2: 布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力

缓存击穿:少数缓存被大量访问,过期的时候,依然大量请求,数据库压力过大


发生在爆款商品,一个单品流量极大的情况下

key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

1. mutex key,互斥锁,只让一个线程去请求数据库写入缓存,而不是同步多个线程去请求数据库
Redis命令为SETNX key value
将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。

返回值
返回整数,具体为
– 1,当 key 的值被设置
– 0,当 key 的值没被设置

伪代码

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
      		if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功,我锁上了,其他人别动
               		value = db.get(key); //数据库请求,读取数据
                      redis.set(key, value, expire_secs); //缓存写入   新问题:如果执行到这一步,服务器挂了,造成死锁
                      redis.del(key_mutex); 			//我干活完成,解锁
              } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
                      sleep(50);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
 }

value = db.get(key); //数据库请求,读取数据 这一步如果执行操作超过锁的时间3秒,那么其他线程就能获取锁。造成其他线程也开始执行数据读取的操作,这个是个死锁问题了

属于分布式锁的问题。这个问题将单独列一篇出来。

2. 对于爆款商品,设置为永久缓存

3. 半永久缓存,设置过期时间比如标记缓存过期为30分钟,但是设置数据库缓存为50分钟,有个线程在后台扫描这些数据,如果到了30分钟就更新一次缓存,但是在这时候如果更新没有完成,其实还是在读取旧的缓存数据

缓存雪崩:大批缓存同时过期,同时请求数据库


当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

1. 设置缓存为随机时间到期,而不是同时,比如商品页面不是全部设置为30分钟,而是随机为25-35分钟
2. 半永久缓存,设置过期时间比如标记缓存过期为30分钟,但是设置数据库缓存为50分钟,有个线程在后台扫描这些数据,如果到了30分钟就更新一次缓存,但是在这时候如果更新没有完成,其实还是在读取旧的缓存数据
3. 锁队列,让更新操作采用分布式锁(当数据并发很大,缓存雪崩的时候,排队更新减少了数据库压力,但是前端服务很难跟上了,会大量页面加载等待失败)

本文引发的新的研究
1.什么事布隆过滤器
2.分布式锁问题

https://www.cnblogs.com/xichji/p/11286443.html


This entry was posted in JAVA and tagged , , , , , . Bookmark the permalink.
月小升QQ 2651044202, 技术交流QQ群 178491360
首发地址:月小升博客https://java-er.com/blog/redis-cache-down/
无特殊说明,文章均为月小升原创,欢迎转载,转载请注明本文地址,谢谢
您的评论是我写作的动力.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*