布隆过滤器在redisson中的使用

布隆过滤器在redisson中的使用

数据库的数据是存储在磁盘上的,高速访问会存在性能问题,使用缓存中间件Redis,可以缓解数据访问的压力;同时数据库查询不到的数据会放在缓存中,并存入 NULL 值,降低数据库消耗;但是若是这样的NULL值过多则会降低缓存性能,什么方式能过滤掉这些无意义的查询,布隆过滤器由此而生

本质:

​ 布隆过滤器使用Bit-map(位图)进行标记,达到判断“一定不存在和可能存在”的目的

解决什么问题:

​ redis缓存穿透

基于redisson的BloomFilter的使用

1.引入redisson工具maven依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.12.3</version>
</dependency>

2.修改springboot配置文件

redisson:
  host:
    config: redis://192.168.152.129:6379
# slf4j日志配置
logging:
  # 配置级别
  #分包配置级别,即不同的目录下可以使用不同的级别
  level:
    com: debug
  # 在不指定路径,只指定输出日志的文件名,默认输出至当前项目下
  # 若指定,则会输出至指定目录下
  file:
    path: log\book.log

3.新建conf层

@Configuration
public class RedissonConf {//加载redisson配置
    @Autowired
    private Environment env;
    @Bean
    public RedissonClient redissonClient(){
        Config cfg=new Config();
        cfg.useSingleServer().
                setAddress(env.getProperty("redisson.host.config")).
                setKeepAlive(true);
        
        return Redisson.create(cfg);
    }
}

4.BloomFilter数值过滤

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RedissonTest {
    //定义日志
    private static final Logger log= LoggerFactory.getLogger(RedissonTest.class);
    //定义操作Redisson的客户端实例
    @Autowired
    private RedissonClient redissonClient;
    @Test
    public void test1(){
        String key="MyBloom";
        Integer total=100000;
        RBloomFilter<Integer> bloomFilter=redissonClient.getBloomFilter(key);
        //初始化布隆过滤器
        bloomFilter.tryInit(total,0.01);//精度越高,消耗空间越大
        //生成元素
        for(int i=1;i<=total;i++){
            bloomFilter.add(i);
        }
        log.info("测试该布隆过滤器里面是否含有1:{}",bloomFilter.contains(1));
        log.info("测试该布隆过滤器里面是否含有-1:{}",bloomFilter.contains(-1));
        log.info("测试该布隆过滤器里面是否含有100:{}",bloomFilter.contains(100));
        log.info("测试该布隆过滤器里面是否含有10000:{}",bloomFilter.contains(10000));
    }
}

5.BloomFilter键值过滤

我们先建立dto层

@Data
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class BloomDto implements Serializable {
    private Integer id;
    private String msg;
}

然后查询

@Test
public void test2(){
    String key="MyBloom1";
    Integer total=1000;
    RBloomFilter<BloomDto> bloomFilter=redissonClient.getBloomFilter(key);
    //初始化布隆过滤器
    bloomFilter.tryInit(total,0.01);

    bloomFilter.add(new BloomDto(100,"北京"));
    bloomFilter.add(new BloomDto(101,"上海"));
    bloomFilter.add(new BloomDto(102,"深圳"));
    bloomFilter.add(new BloomDto(103,"武汉"));
    bloomFilter.add(new BloomDto(104,"哈尔滨"));

    log.info("该布隆过滤器是否包含数据(1,\"1\"):{}",bloomFilter.contains(new BloomDto(1,"1")));
    log.info("该布隆过滤器是否包含数据(1,\"北京\"):{}",bloomFilter.contains(new BloomDto(1,"北京")));
    log.info("该布隆过滤器是否包含数据(101,\"上海\"):{}",bloomFilter.contains(new BloomDto(101,"上海")));
    log.info("该布隆过滤器是否包含数据(104,\"哈尔滨\"):{}",bloomFilter.contains(new BloomDto(104,"哈尔滨")));
}

6.Bloomfltermap过滤

先建RMapDto

@Data
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class RMapDto implements Serializable {
    private Integer id;
    private String name;
}

查询

@Test
public void test3(){//map形式存储
    String key="MyBloom2";
    RMap<Integer,RMapDto> rmap=redissonClient.getMap(key);
    RMapDto dto1=new RMapDto(1,"map1");
    RMapDto dto2=new RMapDto(2,"map2");
    RMapDto dto3=new RMapDto(3,"map3");
    RMapDto dto4=new RMapDto(4,"map4");
    RMapDto dto5=new RMapDto(5,"map5");
    RMapDto dto6=new RMapDto(6,"map6");
    RMapDto dto7=new RMapDto(7,"map7");
    RMapDto dto8=new RMapDto(8,"map8");

    rmap.put(dto1.getId(),dto1);
    rmap.putIfAbsent(dto2.getId(),dto2);
    rmap.putIfAbsentAsync(dto3.getId(),dto3);
    rmap.putAsync(dto4.getId(),dto4);
    rmap.fastPut(dto5.getId(),dto5);
    rmap.fastPutIfAbsent(dto6.getId(),dto6);
    rmap.fastPutAsync(dto7.getId(),dto7);
    rmap.fastPutIfAbsentAsync(dto8.getId(),dto8);

    log.info("---往映射数据结构RMap中添加数据元素完毕---");
}

@Test
public void test4() {//map形式查询
    //String key="MyBloom1";
    //RMap<Integer,RMapDto> rmap=redissonClient.getMap(key);
	//此处若key并不存在会报错:channel: [id: 0xc0ad866d, L:/192.168.152.1:63613 - R:192.168.152.129/192.168.152.129:6379] command: (HLEN), params: [MyBloom1]
    String key="MyBloom2";
    RMap<Integer,RMapDto> rmap=redissonClient.getMap(key);
    Set<Integer> ss=rmap.keySet();
    Map<Integer,RMapDto> map=rmap.getAll(ss);
    log.info("元素列表:{} ",map);

    rmap.remove(6);//指定删除
    log.info("元素列表:{} ",rmap.getAll(ss));

    Integer is[] ={1,2,3};//快速删除
    rmap.fastRemove(is);
    log.info("元素列表:{} ",rmap.getAll(ss));
}

设置过期时间、异步存储

@Test
public void test5() {//map形式存储
    String key="MyBloom3";
    RMapCache<Integer,RMapDto> rmap=redissonClient.getMapCache(key);

    RMapDto dto1=new RMapDto(1,"map1");
    RMapDto dto2=new RMapDto(2,"map2");
    RMapDto dto3=new RMapDto(3,"map3");
    RMapDto dto4=new RMapDto(4,"map4");
    RMapDto dto5=new RMapDto(5,"map5");
    RMapDto dto6=new RMapDto(6,"map6");
    RMapDto dto7=new RMapDto(7,"map7");
    RMapDto dto8=new RMapDto(8,"map8");

    rmap.put(dto1.getId(),dto1);
    rmap.putIfAbsent(dto2.getId(),dto2,5, TimeUnit.SECONDS);
    rmap.putIfAbsentAsync(dto3.getId(),dto3);
    rmap.putAsync(dto4.getId(),dto4);
    rmap.fastPut(dto5.getId(),dto5,10,TimeUnit.SECONDS);
    rmap.fastPutIfAbsent(dto6.getId(),dto6);
    rmap.fastPutAsync(dto7.getId(),dto7);
    rmap.fastPutIfAbsentAsync(dto8.getId(),dto8);

    Set<Integer> ss=rmap.keySet();
    Map<Integer,RMapDto> map=rmap.getAll(ss);
    log.info("元素列表:{} ",map);

    try {
        Thread.sleep(5000);
        Set<Integer> ss1=rmap.keySet();
        Map<Integer,RMapDto> map1=rmap.getAll(ss1);
        log.info("5s元素列表:{} ",map1);

        Thread.sleep(5000);
        Set<Integer> ss2=rmap.keySet();
        Map<Integer,RMapDto> map2=rmap.getAll(ss2);
        log.info("又5s元素列表:{} ",map2);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
元素列表:{1=RMapDto(id=1, name=map1), 2=RMapDto(id=2, name=map2), 3=RMapDto(id=3, name=map3), 4=RMapDto(id=4, name=map4), 5=RMapDto(id=5, name=map5), 6=RMapDto(id=6, name=map6), 7=RMapDto(id=7, name=map7), 8=RMapDto(id=8, name=map8)} 
5s后元素列表:{1=RMapDto(id=1, name=map1), 3=RMapDto(id=3, name=map3), 4=RMapDto(id=4, name=map4), 5=RMapDto(id=5, name=map5), 6=RMapDto(id=6, name=map6), 7=RMapDto(id=7, name=map7), 8=RMapDto(id=8, name=map8)} 
又5s后元素列表:{1=RMapDto(id=1, name=map1), 3=RMapDto(id=3, name=map3), 4=RMapDto(id=4, name=map4), 6=RMapDto(id=6, name=map6), 7=RMapDto(id=7, name=map7), 8=RMapDto(id=8, name=map8)} 
2020-11-27 20:09:40.398  INFO 14896 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
Process finished with exit code 0

由最后的结果可见布隆过滤器的基本使用暂没出现什么问题

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值