布隆过滤器解决缓存穿透方案附上代码
「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
概述
缓存击穿,大家多多少少听说过。那么这个问题到底是个什么问题?怎么解决呢?这个问题其实是在高并发场景下,使用缓存提高访问速度,一些非法访问或者说攻击刻意绕过缓存,来直接攻击我们数据库。导致我们缓存形同虚设,并没有起到缓存效果。这个问题解决的根本就是过滤掉非法请求,只允许访问合法数据即可,而布隆过滤器就是用来过滤非法请求的,能达到我们预想的效果。
布隆过滤器原理
原理图
1.首先会初始化一个全0比特位的数组,这个数组长度取决于用户期望存储数据的个数size,以及用户期望的误判率 fpp,根据用户size和fpp,会计算一个能存储下的bit数组,进行初始化,并且确定使用几个hash函数。
2.用户每存一条数据,同时将key设置到布隆过滤器中,那么布隆过滤器会根据初始化的多个hash函数分别进行计算 ,每个hash函数会计算一个布隆过滤器数组的下标,并且置为1
3.当用户判断一个key存在不存在时,布隆过滤器会重复2的步骤,看看是否全为1,如果是,那么数据存在
4.存在hash冲突,很有可能两个不同key通过hash计算,最后的数组下标会一模一样,从而导致误判。但是不存在的 数据一定不存在。
优缺点
优点:节省空间,不需要存储真实数据来判断数据是否存在
缺点:存在一定误判,因为hash冲突原因,是会产生误判的,虽然可以设置,但是性能会受一定影响
解决缓存穿透问题
布隆数据预热
/**
* 数据预热Bloom
*/
public void readyBloom(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.select("id");
List<User> users = userMapper.selectList(userQueryWrapper);
for (User user:users){
bloomFilter.put(user.getId());
}
}
1.一般情况下,布隆过滤器都是业务后期加入的,业务初期数据库压力不大,一些缓存穿透攻击可以接受,不会影响正常业务处理;一般都是后期业务压力变大,再加入一些非法攻击,会导致服务雪崩宕机之类风险 2.布隆过滤器预热,只需要将将来作为判断的key加入布隆过滤器即可
布隆过滤器同步增量更新
public String guavaBloomTestSet(User user){
//插入数据
userMapper.insert(user);
//加到布隆过滤器
bloomFilter.put(user.getId());
return "success";
}
更新数据同时,需要同步到布隆过滤器中,否则导致有数据查不出来的情况
布隆过滤器过滤非法数据处理
public User guavaBloomTestGet(@PathVariable Integer id){
//判断布隆过滤器是否存在
if(bloomFilter.mightContain(id)){
//获取缓存数据
String s = stringRedisTemplate.opsForValue().get(PREFIX+id.toString());
if(s==null){
//缓存不存在,查询数据库
User user = userMapper.selectById(id);
//空值处理(布隆误判 | 数据被删)
String value=user==null?"":JSONUtil.toJsonStr(user);
//加入缓存
stringRedisTemplate.opsForValue().set(PREFIX+id.toString(), value, Duration.ofSeconds(300L));
return user;
}else if(s.equals("")){
//缓存空值处理
return null;
}else {
return JSONUtil.toBean(s,User.class);
}
}
//不存在布隆过滤器直接返回
return null;
}
1.key存在布隆过滤器中,缓存没数据,那么查数据库(有数据),同时更新缓存
2.key存在布隆过滤器中,缓存没数据,那么查数据库(无数据),同时更新缓存(更新空值),属于误判的情况,或者数据之前存在,业务需求被删除
3.key存在布隆过滤器中,缓存有数据(空值),直接返回
4.key存在布隆过滤器中,缓存有数据(有值),直接返回(反序列化)
5.key不存在布隆过滤器中,直接返回null
扩展
基于场景考虑,有单机版布隆过滤器(guava),有分布式版布隆过滤器(redisson)
总结
通过布隆过滤器来拦截一些不在业务之内的非法请求,从而达到保护服务的作用;注意布隆并不能分担正常业务的流量压力。
转载自:https://juejin.cn/post/7068578263638999048