使用BloomFilter(布隆过滤器)可解决缓存穿透问题
1.导入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
2.配置redisson
@Configuration
public class RedissonConfig {
//从application.properties中获取spring.redis.host配置
@Value("${spring.redis.host}")
private String redisHost;
//从application.properties中获取spring.redis.port配置
@Value("${spring.redis.port}")
private int redisPort;
//从application.properties中获取bloomfilter.v1参数
@Value("${bloomfilter.v1}")
private Long v1;
//从application.properties中获取bloomfilter.var3容错率参数
@Value("${bloomfilter.var3}")
private double var3;
//将redissonClient配置为springBean后可以重新根据自己需要配置loomFilter
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress("redis://"+redisHost+":"+redisPort);
return Redisson.create(config);
}
//配置默认的loomFilter
@Bean
public RBloomFilter<String> bloomFilter(){
RBloomFilter<String> bloomFilter=redissonClient().getBloomFilter("bloom-filter");
bloomFilter.tryInit(v1,var3);
return bloomFilter;
}
}
3.初始化bloomfilter内容
@Component
public class StartUser implements ApplicationRunner{
@Autowired
private UserMapper userMapper;
@Autowired
private RedissonConfig redissonConfig;
private RBloomFilter<String> rbloomFilter;
@PostConstruct
public void init(){
rbloomFilter = redissonConfig.bloomFilter();
}
@Override
public void run(ApplicationArguments args) {
List<User> users = userMapper.selectList();
value.stream().map(User->{
rbloomFilter.add(User.getUserId());
return null;
}).collect(Collectors.toList());
}
}
4.使用,判断是否存在,不存在不让查询数据库
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Autowired
private RedissonConfig redissonConfig;
private RBloomFilter<String> rbloomFilter;
@PostConstruct
public void init(){
rbloomFilter = redissonConfig.bloomFilter();
}
public ApiRes getUserById(String userId){
//布隆过滤器拦截
boolean contains = rbloomFilter.contains(userId);
if (!contains){
return ApiRes.fail(407,"userId不存在!");
}
User user=userMapper.getUserById(userId);
return ApiRes.success(user);
}
}