Redis缓存结构
什么是缓存穿透?
用户发送请求查询了一条数据,但是数据库并没有这条数据,数据库没有这条数据,缓存中肯定也没有这条数据,所以这个请求就越过了缓存去数据库中查询,数据库查询不到返回空值,而这种场景就称之为缓存穿透
缓存穿透的危害?
试想若是在高并发的情况下,缓存被穿透了导致数据库压力倍增甚至会出现宕机,若是被别人恶意访问缓存穿透又会造成怎样的后果?
解决方案
1.简单粗暴的方式:如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
2.布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
这里只介绍布隆过滤器感觉第一种方式没啥可介绍的
需要依赖
<!-- guava 引入布隆过滤器 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
布隆过滤器工具类
@Component
public class BloomFilterImpl {
// 预存的数据个数 100w
private static int size = 1000000;
// 创建布隆过滤器的对象 3.容错率容错率越小越费性能越安全
private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(),size,0.001);
@Resource
private UserDao userDao;
/**
* BloomFilterImpl对象被创建后,立即初始化的方法
*/
@PostConstruct
public void initData(){
// 查询数据库中所有的id的值
List<Integer> ids = userDao.selectAllIds();
// 初始化到布隆过滤器中
for (Integer id : ids) {
bloomFilter.put(id);
}
}
/**
* 判断布隆过滤器中是否存在该id
* @param id
* @return
*/
public boolean mightContain(Integer id){
return bloomFilter.mightContain(id);
}
}
使用方式就不介绍了,只需在访问数据库前判断布隆过滤器中是否存在即可