### **缓存穿透**
**描述**
缓存穿透是指用户不断请求查询缓存和数据库中都没有的数据,出于容错的考虑,如果从缓存中查不到数据则会去数据库中查询,因此缓存穿透也将导致每次请求都会到数据库中去查询,失去了缓存的意义。
**解决方案:**
缓存空对象:将缓存和数据库中都不存在的数据,对key进行set (key,null),并设置缓存的有效时间
### **缓存击穿**
**描述**
缓存击穿是指redis中存在对应key的数据,但在缓存时间过期之后,有大量并发请求在缓存中查询不到数据后会去数据库查询数据,引起数据库压力过大。
**解决方案:**
1. 缓存持久化存储
2. 互斥锁:在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。
只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。
![](https://img.kancloud.cn/86/ee/86eea2cc0bccea34d6bb4482d03daf74_908x598.png)
### **缓存雪崩**
**描述**
当缓存服务器重启或者大量缓存集中在某一个时间段失效,而引起数据库压力过大,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了。
**解决方案:**
1. 存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
2. 用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写