JAVA布隆过滤器的使用BloomFilter

需求:对于一些url的去重若果量大的话使用redis会卡顿的,使用缓存还要考虑持久化,系统一关就没了.

于是就百度了一下布隆过滤器刚刚好,处理上亿数据也很快,站内存也小.

用法:

1.自己实现(可能不稳定,功能不是太多,一个添加,一个判断是否添加过了)

2.感谢java强大的生态,谷歌的guava工具里竟然有这个工具(我给写了工具类,方便吧数据给放到文件里,实现了持久化,不怕关机后数据没有了)

1.自己实现的
package cn.cpc.bloomfilter;


import java.util.BitSet;

public class SimpleBloomFilter {

    private static final int DEFAULT_SIZE = 2 << 24;
    private static final int[] seeds = new int[]{7, 11, 13, 31, 37, 61,};

    private BitSet bits = new BitSet(DEFAULT_SIZE);
    private SimpleHash[] func = new SimpleHash[seeds.length];


    public SimpleBloomFilter() {
        for (int i = 0; i < seeds.length; i++) {
            func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
        }
    }

    public void add(String value) {
        value = value.trim();
        for (SimpleHash f : func) {
            bits.set(f.hash(value), true);
        }
    }

    public boolean contains(String value) {
        value = value.trim();
        if (value == null) {
            return false;
        }
        boolean ret = true;
        for (SimpleHash f : func) {
            ret = ret && bits.get(f.hash(value));
        }
        return ret;
    }


}

用现成的 谷歌的guava工具
1.导入jar包
<!-- guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.1-jre</version>
        </dependency>
2.上工具
package cn.cpc.util;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;

public class BloomFilterUtil {

    private static int size = 1000000;

    private static BloomFilter<String> bloomFilter = null;

	//获取一个布隆过滤器
	fileName:持久化的文件名,这里是相对路径,就在本项目下
    public static BloomFilter<String> getStringBloomFilter(String fileName){

        try {
            File file = new File("filter");
            if (!file.exists()){
                System.out.println("持久化文件不存在!,将创建文件,布隆过滤器为空");
                bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), size);
            }else{
                System.out.println("持久化文件存在!,从文件读取数据到布隆过滤器");
                FileInputStream fileInputStream = new FileInputStream(file);
                bloomFilter = BloomFilter.readFrom(fileInputStream, Funnels.stringFunnel(Charset.defaultCharset()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bloomFilter;
    }

//吧布隆过滤器的储存到硬盘(持久化操作,也可以放数据库)
fileName:持久化的文件名,这里是相对路径,就在本项目下
    public static void write(String fileName){
        try {
            bloomFilter.writeTo(new FileOutputStream(new File(fileName)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}

### 布隆过滤器在解决缓存穿透问题中的应用 布隆过滤器(Bloom Filter)作为一种高效的空间节省型数据结构,被广泛应用于各种场景下的快速成员检测。它特别适合用来处理大规模数据集的查询操作,尤其是在需要判断某个元素是否属于某一集合的情况下。以下是关于如何利用布隆过滤器防止缓存穿透的具体方案: #### 工作原理概述 布隆过滤器的核心是由一个长度固定的比特数组以及多个独立的哈希函数组成[^1]。当向其中插入新元素时,这些哈希函数会分别计算出对应的位置索引并将相应位置上的值置为1;而在查找阶段,则只需验证所有指定位置是否均为1即可得出结论——如果存在任何一个零值,则表明目标对象肯定不属于当前集合。 然而值得注意的是,由于可能存在不同元素经过各自不同的哈希运算后指向完全相同的几个位的情况发生冲突从而造成假阳性结果的现象,即对于那些实际上并不存在于原始集合内的项目也可能被判别成“可能包含”。尽管如此,只要合理控制参数配置如预期最大容量N与允许误差率p之间关系等因素的影响程度,就可以使得最终产生的误判几率保持在一个较低水平范围内接受范围之内[^2]。 #### Java 实现案例分析 下面给出一段基于 Google Guava 库实现的一个简单例子展示怎样构建这样一个用于预防缓存击穿现象出现的基础框架结构: ```java // 导入必要的类库 import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; public class CachePenetrationPrevention { // 定义静态变量保存全局唯一实例化的布隆过滤器对象 private static final BloomFilter<String> BLOOM_FILTER; static{ // 构造方法调用前先完成初始化工作 int expectedInsertions = 100000; // 预估最多容纳多少条记录 double fpp = 0.01d; // 可容忍的最大错误概率百分比 // 调用工厂模式创建具体的布隆过滤器实体 BLOOM_FILTER = BloomFilter.create( Funnels.stringFunnel(StandardCharsets.UTF_8), expectedInsertions, fpp); // 将一些已知有效的key预先加载进去形成基础底座 preloadKnownKeys(); } /** * 模拟预填充部分常见合法请求路径作为白名单参照物 */ private static void preloadKnownKeys(){ String[] knownValidRequests={"itemA","productB","serviceC"}; for(String key : knownValidRequests){ putIntoBloomFilter(key); } } /** * 把给定字符串形式的关键字加入到布隆过滤器当中去 * @param key 待录入的新关键字 */ public static void putIntoBloomFilter(String key){ if(!mightContainInBloomFilter(key)){ BLOOM_FILTER.put(key); } } /** * 测试传进来待测关键词是否有可能已经收录过来了呢? * @param key 输入测试的目标关键字 * @return 返回布尔类型的判定答案 */ public static boolean mightContainInBloomFilter(String key){ return BLOOM_FILTER.mightContain(key); } } ``` 在这个示例代码片段里展示了完整的生命周期管理流程图谱:从最开始定义好固定规格大小直至最后提供对外公开接口供其他模块调用为止整个过程一览无余。通过这种方式不仅可以有效减少不必要的数据库负载压力而且还能大幅提升整体响应速度体验效果明显优于传统单一层次防护措施单独作战所能达到的高度。 --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值