布隆过滤器

BloomFilter(布隆过滤):将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。在缓存之前在加一层 BloomFilter,在查询的时候先去 BloomFilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 -> 查 DB。

redis中没有需要的key,直接穿过redis访问数据库了。
bitmap是一组二进制数组,每个需要存储到redis的key,使用若干个哈希算法计算出若干个数组下标;
比如hello的下标是hash1()->1,hash2()->2,hash3()->3,hash4()->4。那么就会把下标为1,2,3,4的数组元素改为1,
比如hi的下标是2,3,4,5那么也会把2,3,4,5的数组元素改为1。
这样就可以通过相应位置数组值是否为1判断redis中是否存在这个key。
当然也会有误判出现,当不同的key通过若干哈希算法得到数组下标一样时,就会造成误判。
设置布隆过滤器时需要设置
1,需要存储的key数量
2,误差率,因为误差率越小,需要的hash算法的数量也就越多,bitmap的长度也就越长。

pom依赖

<!--布隆过滤器-->
<dependency>
     <groupId>org.redisson</groupId>
     <artifactId>redisson-spring-boot-starter</artifactId>
     <version>3.16.7</version>
 </dependency>

配置布隆过滤器

/**
 * 配置布隆过滤器
 */
@Configuration
public class BloomFilterConfig {
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 布隆过滤器
     * 布隆过滤器可以判断是否大概率存在某个key,存在一定的误差
     * 取决于设置的错误比例,根据插入数量、允许错误比例设置2进制数组,根据多个hash函数计算数组下标,将对应下标改为1
     * 所以就存在不同的key计算出的数组下标相同的情况,那么就会造成误判
     * @return
     */
    @Bean
    public RBloomFilter<String> orderBloomFilter() {
        //过滤器名称
        String filterName = "myBloomFilter";
        // 预期插入数量
        long expectedInsertions = 10000L;
        // 错误比率
        double falseProbability = 0.01;
        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(filterName);
        bloomFilter.tryInit(expectedInsertions, falseProbability);
        return bloomFilter;
    }
}

设置redis缓存后,将key保存到布隆过滤器中
查询缓存前,先查询布隆过滤器是否大概率存在这个key,如果存在就获取,如果不存在就返回,防止请求直接打到数据库上,防止缓存穿透

@Component
public class RedisTask {
    Log log = LogFactory.getLog(RedisTask.class);
    private final RedisUtils redisUtils;
    @Autowired
    public RedisTask(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }
    @Resource
    private RBloomFilter<String> myBloomFilter;
    @PostConstruct
    public void task1() {
        RedisValueDO valueDO = new RedisValueDO();
        valueDO.setId(1);
        valueDO.setStation("910");
        valueDO.setTime(new Date());
        //1,设置redis缓存
        String key =  "login:" + UUID.randomUUID();
        redisUtils.set(key, valueDO, AuthConstant.EXPIRATION_TIME_IN_SECOND, TimeUnit.SECONDS);
        //2,key保存到布隆过滤器
        log.info("布隆过滤器中添加key:"+ key);
        myBloomFilter.add(key);


        //根据布隆过滤器判断key是否可能存在
        if(myBloomFilter.contains(key)){
            //获取redis值
            RedisValueDO value = (RedisValueDO)redisUtils.get(key);
            if(!Objects.isNull(value)){
                log.info("命中缓存");
            }else {
                //3、缓存不存在则查询数据库
                log.info("未命中缓存,查询数据库");
                //重新设置缓存
                redisUtils.set(key, valueDO, AuthConstant.EXPIRATION_TIME_IN_SECOND, TimeUnit.SECONDS);
            }
        }else {
            log.info("判定key不存在,不进行查询");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值