springboot-redis-redisson-bloomfilter布隆过滤器

springboot-redis-redisson-bloomfilter布隆过滤器

  • Redis中的布隆过滤器
  • springboot中使用布隆过滤器
    • 1.pom.xml依赖
    • 2.properties配置文件
    • 3.Redisson配置
    • 4.测试类
    • 5.结果
    • 6.分析

Redis中的布隆过滤器

使用场景: 爬虫url去重,阅读列表去重等;

Redis4.0及以后以插件的形式提供了布隆过滤器;

本文主要讲解Redisson实现的布隆过滤器;
Redisson中的布隆过滤器,使用一个string存储数据。使用一个hash存储过滤器的配置信息,如初始大小,容错率等;
springboot-redis-redisson-bloomfilter布隆过滤器_第1张图片
springboot-redis-redisson-bloomfilter布隆过滤器_第2张图片
原理: 就是使用多个hash算法得到分别得到数值,将这些数值在string所在的bit位设置为1,表示出现过。为0的表示没出现过;下次来一个值,同样进行多次hash得到数值,分别判断这些数值位置上的值,只要一个为0,就认为不存在,否则返回存在;

布隆过滤器认为一个值在其中,那么不一定在其中;
认为一个值不在其中,那么一定不在其中;

springboot中使用布隆过滤器

1.pom.xml依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
    <groupId>org.redissongroupId>
    <artifactId>redisson-spring-boot-starterartifactId>
    <version>3.14.1version>
dependency>

redisson-spring-boot-starter依赖相对于单独依赖reddisson更完整

2.properties配置文件

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.1.7
#spring.redis.cluster.nodes=127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
#spring.redis.password=Anfang@123!
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8

# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000
# 看门狗时间,到时还没释放则延长
spring.redis.lock-watchdog-timeout=100
server.port=8001

3.Redisson配置

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * Redis配置文件的参数
 */
@Data
@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
     
    private String host;
    private int port;
    private String password;
    private int database;
    private int lockWatchdogTimeout;
}

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Redission配置类
 */
@Slf4j
@Configuration
public class RedissionConfig {
     

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public RedissonClient redissonClient() {
     
        RedissonClient redissonClient;

        Config config = new Config();
        //starter依赖进来的redisson要以redis://开头,其他不用
        String url = "redis://"+ redisProperties.getHost() + ":" + redisProperties.getPort();
        config.useSingleServer().setAddress(url)
                .setPassword(redisProperties.getPassword())
                .setDatabase(redisProperties.getDatabase());

        try {
     
            redissonClient = Redisson.create(config);
            return redissonClient;
        } catch (Exception e) {
     
            log.error("RedissonClient init redis url:[{}], Exception:", url, e);
            return null;
        }
    }

}

4.测试类


import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 布隆过滤器demo
 */
@RestController
public class BloomFilterDemo {
     

    @Resource(name = "redissonClient")
    private RedissonClient redissonClient;

    @RequestMapping("/demo")
    public String demo() {
     

        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("bloom-filter");
        //初始化,容量1000,错误率千分之三
        bloomFilter.tryInit(1000, 0.003);
        //add1000个
        for (int i = 0; i < 1000; i++) {
     
            bloomFilter.add("tom " + i);
        }
        int count = 0;
        //查询1000次
        for (int i = 0; i < 1000; i++) {
     
            if (bloomFilter.contains("bob" + i)) {
     
                count++;
            }
        }
        System.out.println("错误个数=" + count);
        System.out.println("'瓜田李下 1'是否存在:" + bloomFilter.contains("瓜田李下 " + 1));
        System.out.println("'海贼王'是否存在:" + bloomFilter.contains("海贼王"));
        System.out.println("预计插入数量:" + bloomFilter.getExpectedInsertions());
        System.out.println("容错率:" + bloomFilter.getFalseProbability());
        System.out.println("hash函数的个数:" + bloomFilter.getHashIterations());
        System.out.println("插入对象的个数:" + bloomFilter.count());

        return null;
    }
}

5.结果

错误=10
'瓜田李下 1'是否存在:false
'海贼王'是否存在:false
预计插入数量:1000
容错率:0.003
hash函数的个数:8
插入对象的个数:978

6.分析

  1. hash函数的个数,容错率越低hash函数的个数越多;
  2. 数据一旦超过预定容量,错误率就会急剧上升;

你可能感兴趣的:(springboot,redis,过滤器,java)