介绍: 布隆过滤器本质是 一种数组这种数据结构+算法演变而来。
原理:将数据通过多种不同的hash函数 得出位置 放到数组当中 保存格式为 0 1(集中hash函数 计算出几个值) ,同时将数据添加到布隆过滤器中,需要查询数据时,会计算数据的hash值,当计算出来的值 所对应的位置全为1时,表示数据一定存在
弊端:数据删除困难,删除时需要值所在位置赋0 但如果其他值计算结果也在这个位置上会影响值。 并且一定不在 就是不在,在不一定就在 有误差率,误差率跟数组大小和hash函数以及其hash函数数量有关
优势:占用空间小 查询速度快,保密性高 无法追溯到元数据
使用场景:大数据查询 是否的场景,缓存穿透场景(无效数据指透过缓存直接查询数据库,增加数据库压力)
工作实际应用场景 二级缓存+布隆过滤器(大量查询)
思路
布隆过滤器用于存储 条件(否)的值 当数据进入方法后 优先使用过滤器判断 过滤掉否的值,拿到剩余查询条件
一级缓存 本地 然后通过一级缓存进行数据查询 过滤掉查询出的值 拿到剩余条件
二级缓存 redis 然后通过redis进行数据查询 过滤掉查询出的值 拿到剩余条件 一二级缓存设置不同缓存时间 保证缓冲
本地mysql 剩余条件进行本地mysql查询
需要考虑如何将在reids不在本地缓存中的数据加入本地缓存
布隆过滤器实际使用代码示例
依赖使用谷歌自带的
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
本地缓存加载
/**
* 布隆过滤器配置
*/
@Configuration
public class BloomConfig {
//预期插入量
public static final int DEFAULT_EXPECTED_INSERTIONS = 1000000;
//误判率
public static final double DEFAULT_FPP = 0.03;
//布隆过滤器名称
public static final String BLOOM_FILTER_NAME = "journalFilter";
public static final String BLOOM_FILE_SOURCE = "C:\Users\Admin\Desktop\pdf\bloom.ser";
// public static final String BLOOM_FILE_SOURCE = "/common-service/bloom.ser";
/**
* 布隆过滤器初始化
* @return
* @throws FileNotFoundException
*/
@Bean(BLOOM_FILTER_NAME)
public BloomFilter bloomFilterConfig() throws FileNotFoundException {
//优先判断有无缓存文件 重启时用
File file = new File(BLOOM_FILE_SOURCE);
if (file.exists()){
try {
return BloomFilter.readFrom(new FileInputStream(file), Funnels.stringFunnel(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new RuntimeException(e);
}
}else {
return BloomFilter.create(Funnels.integerFunnel(), DEFAULT_EXPECTED_INSERTIONS, DEFAULT_FPP);
}
}
}
布隆过滤器写入本地文件
@Resource(name = BloomConfig.BLOOM_FILTER_NAME)
private BloomFilter bloomFilter;
/**
* PreDestroy 容器关闭前调用的方法
*/
@PreDestroy
public void destroyBloomFilter() {
String dist = BloomConfig.BLOOM_FILE_SOURCE;
File file = new File(dist);
if (file.exists()) {
file.delete();
}
try (OutputStream out = Files.newOutputStream(file.toPath())) {
bloomFilter.writeTo(out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
布隆过滤器的新增 以及重新进行初始化
新增 put
初始化 (新建新过滤器 重新赋值)
/**
* 刷新布隆过滤器
*/
public void flushBloomFilter() {
BloomFilter<CharSequence> newFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), BloomConfig.DEFAULT_EXPECTED_INSERTIONS, BloomConfig.DEFAULT_FPP);
//刷新
bloomFilter = newFilter;
}
文章评论