项目实践----Spring Boot项目中加入布隆过滤器

本文以xx点评为例,使用redisson实现布隆过滤器

1、拉取redis

docker run --restart=always -p 6378:6379 --name myredis -d redis:7.0.12

这个命令会创建一个redis实例,如果没有找到该实例,会先联网拉取

创建成功

 如果出现docker: Error response from daemon: Get "https://registry-1.docker.io/v2/":参考Error response from daemon: Get “https://registry-1.docker.io/v2/“.....解决方法-CSDN博客

查看是否创建成功

docker ps

 显示

如果没有出现类似的结果,使用docker ps -a查看所有创建的容器(包括成功启动和失败的),再使用docker logs 容器名  查看创建失败的容器的日志 

2、使用可视化工具连接redis 

使用可视化工具连接redis,方便后续查看结果 

获取redis所在服务器的ip,这里我是在虚拟机中centos7的docker中部署的,使用命令查看服务器ip

ip addr

 获取红色箭头ip

redis可视化工具,这里使用的是RDM

先点击红色箭头,然后在绿色箭头输入信息,名字取啥都行(myredis),地址为上面获得的服务器的ip,还有端口号,然后点击确定即可

 3、在Spring Boot项目中配置

在pom.xml文件中引入redisson依赖

<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.16.5</version>
 </dependency>

在config文件夹中创建两个文件RedissonConfig和BloomFilterConfig

打开RedissonConfig,写入配置代码

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient redissonClient(){
        // 配置
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.50.110:6378");
        // 创建RedissonClient对象
        return Redisson.create(config);
    }
}

 这里的ip和端口号更换为redis所在服务器的ip和redis的端口号

打开RedissonConfig,写入以下代码

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;

@Configuration
public class BloomFilterConfig {

    public static final String BLOOM_FILTER_KEY = "shopBloomFilter";
    private static final int EXPECTED_INSERTIONS = 100000; // 预期的ID数量
    private static final double FALSE_POSITIVE_RATE = 0.01; // 误判率

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IShopService shopService;

    @PostConstruct
    public void initBloomFilter() {
        // 获取布隆过滤器实例
        RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_KEY);

        // 如果布隆过滤器已经存在,则删除
        if (bloomFilter.isExists()) {
            bloomFilter.delete();
        }

        // 初始化布隆过滤器
        bloomFilter.tryInit(EXPECTED_INSERTIONS, FALSE_POSITIVE_RATE);

        // 从数据库中获取所有店铺的ID
        List<Long> ids = shopService.getAllShopIds();

        // 将所有ID添加到布隆过滤器中
        ids.forEach(bloomFilter::add);
    }

}

此处  List<Long> ids = shopService.getAllShopIds() 是自己定义的方法,获取数据库中所有店铺的id;@PostConstruct注解会使得该方法在项目启动的时候初始化,即项目启动后,布隆过滤器会先加载所有id。

4、在业务代码中使用

这里在xx点评中的queryById中使用

5、测试布隆过滤器

配置完后,启动项目测试

布隆过滤器初始化成功,查看RDM可视化工具

创建了一个布隆过滤器且有数据。

 使用postman调用查询id的接口,如下

id为70数据并不在数据库里,所有直接在布隆过滤器这一层就拦截了

 

id为1的数据,数据库中存在,查询成功!

### 布隆过滤器的实现与应用 #### 什么是布隆过滤器布隆过滤器是一种高效的空间节省型概率数据结构,主要用于快速判断某个元素是否属于一个集合[^2]。它通过多个哈希函数将元素映射到一个固定长度的位数组上,并记录这些位置的状态。 #### 布隆过滤器的工作原理 布隆过滤器的核心是由一个很长的二进制向量(即位数组)以及一组独立的哈希函数组成[^4]。以下是其实现的关键步骤: 1. **初始化**:创建一个初始状态全为 `0` 的位数组。 2. **插入元素**:对于每一个新加入的元素,计算该元素对应的一组哈希值,并将其对应的位设置为 `1`。 3. **查询元素**:对于待查元素,同样计算其哈希值并检查相应的位置是否均为 `1`。如果是,则认为可能存在于集合中;如果有任意一位不为 `1`,则肯定不在集合中。 需要注意的是,由于存在多对一的哈希冲突可能性,因此布隆过滤器可能会产生误报(False Positive),但不会漏报(False Negative)。这意味着如果布隆过滤器表示某元素“可能存在”,那么需要进一步验证;但如果表示“一定不存在”,则是绝对可靠的。 #### Python中的布隆过滤器实现 下面提供了一个简单的布隆过滤器实现示例: ```python import mmh3 from bitarray import bitarray class BloomFilter: def __init__(self, size, hash_num): self.size = size self.hash_num = hash_num self.bit_array = bitarray(size) self.bit_array.setall(0) def add(self, item): for i in range(self.hash_num): digest = mmh3.hash(item, i) % self.size self.bit_array[digest] = 1 def check(self, item): for i in range(self.hash_num): digest = mmh3.hash(item, i) % self.size if not self.bit_array[digest]: return False return True # 使用示例 bf = BloomFilter(500000, 7) bf.add("hello") print(bf.check("hello")) # 输出True print(bf.check("world")) # 可能输出False或True (取决于hash碰撞情况)[^2] ``` #### 应用场景分析 布隆过滤器因其高效率和低内存占用,在多种实际场景中有广泛应用[^5]: - **爬虫系统的 URL 去重**:避免重复抓取相同网页链接。 - **垃圾邮件过滤**:存储已知垃圾邮件特征信息,提高检测速度。 - **防止缓存穿透**:拦截那些根本不存在于数据库中的请求,减轻服务器负担。 - **数据库查询优化**:提前筛选掉不可能匹配的结果集,减少不必要的 I/O 操作。 #### 局限性和注意事项 虽然布隆过滤器非常有用,但也有一些局限性需注意: - 它无法删除已经添加进去的数据项,除非重新构建整个滤波器。 - 存在一定的假阳性率,这取决于所选参数如位数组大小、哈希函数数目等因素[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值