使用Redission来实现布隆过滤器

news2025/5/21 2:19:26

简述布隆过滤器

布隆过滤器是一种概率型数据结构,它可以用来判断一个元素是否在一个集合中。我们当时使用的是Redisson实现的布隆过滤器。它的底层原理是,先初始化一个比较大的数组,里面存放的是二进制0或1。一开始都是0,当一个key来了之后,经过3次hash计算,模数组长度找到数据的下标,然后把数组中原来的0改为1。这样,三个数组的位置就能标明一个key的存在。当需要判断一个元素是否存在时,通过相同的哈希函数计算出该元素在位数组上的位置,如果这些位置上的值都为1,则认为该元素可能存在;如果任何一个位置上的值为0,则该元素一定不存在。在缓存穿透的场景中,我们可以将数据库中存在的数据对应的key存入布隆过滤器,当查询一个key时,先通过布隆过滤器判断该key是否存在,如果不存在,直接返回,避免查询数据库。

为什么会产生误判

误判的产生是由于多个不同的元素可能通过哈希函数映射到位数组的相同位置。这种情况称为哈希冲突。由于布隆过滤器使用多个哈希函数,一个元素的每个哈希值都对应位数组中的一个位置,这意味着不同元素的哈希值可能会重叠。

例如,如果两个不同的元素通过哈希函数计算后都映射到位数组的同一个位置,并且这个位置最初是0,那么当第一个元素被添加到布隆过滤器时,该位置会被设置为1。当第二个元素被检查时,由于该位置已经是1,布隆过滤器可能会错误地认为第二个元素也存在于集合中,即使它实际上并不存在。

减少误判的方法

  1. 增加位数组的大小:更大的位数组可以减少哈希冲突的概率,从而降低误判率。

  2. 增加哈希函数的数量:更多的哈希函数可以更均匀地分布元素到位数组中,但也会增加计算成本。

  3. 选择合适的哈希函数:好的哈希函数可以减少冲突的概率。

布隆过滤器怎么更新和删除内容,有实现的思路吗?

布隆过滤器是一种只支持添加元素,理论上不支持删除元素的数据结构,因为它使用多个哈希函数将元素映射到位数组的多个位置,删除一个元素可能会影响其他元素的检查结果。不过,有一些方法可以间接实现删除操作或者更新布隆过滤器的内容。

1. 重新创建布隆过滤器

最简单直接的方法是重新创建一个布隆过滤器,将需要保留的元素重新添加进去。这种方法成本较高,因为它需要重新计算所有保留元素的哈希值并更新位数组。

2. 使用计数器(Counting Bloom Filter)

计数布隆过滤器(Counting Bloom Filter)是布隆过滤器的一种变体,它使用计数数组代替位数组,每个位置存储一个计数值而不是简单的0或1。这样,删除元素时可以将对应位置的计数值减1,而不是直接置为0。这种方法可以支持删除操作,但增加了存储空间和计算复杂度。

使用Redission来实现布隆过滤器的步骤

 1. 添加Redission依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.15.6</version> <!-- 请检查最新版本 -->
</dependency>

2. 配置Redission

在应用启动时,配置Redisson客户端以连接到Redis服务器:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonConfig {
    public static RedissonClient create() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379"); // Redis服务器地址
        return Redisson.create(config);
    }
}

3. 使用Redisson创建和使用布隆过滤器

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;

public class BloomFilterExample {
    private static final RedissonClient redisson = RedissonConfig.create();

    public static void main(String[] args) {
        // 创建布隆过滤器,预计元素数量为1000,误判率为0.03
        RBloomFilter<String> bloomFilter = redisson.getBloomFilter("myBloomFilter");
        bloomFilter.tryInit(1000, 0.03);

        // 添加元素到布隆过滤器
        bloomFilter.add("key1");
        bloomFilter.add("key2");

        // 检查元素是否存在于布隆过滤器
        boolean exists1 = bloomFilter.contains("key1"); // 应该返回true
        boolean exists2 = bloomFilter.contains("key2"); // 应该返回true
        boolean exists3 = bloomFilter.contains("key3"); // 可能返回false或true(误判)

        System.out.println("key1 exists: " + exists1);
        System.out.println("key2 exists: " + exists2);
        System.out.println("key3 exists: " + exists3);
    }
}

4. 处理缓存穿透

在缓存穿透的场景中,使用布隆过滤器来避免不必要的数据库查询

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;

public class CacheService {
    // 获取Redisson客户端实例,确保已经配置好Redisson
    private static final RedissonClient redisson = RedissonConfig.create();
    // 使用Redisson创建布隆过滤器,名称为"myBloomFilter"
    private static final RBloomFilter<String> bloomFilter = redisson.getBloomFilter("myBloomFilter");

    /**
     * 获取数据的方法。
     * 先通过布隆过滤器检查key是否存在,如果不存在则直接返回null。
     * 如果存在,从数据库查询数据,并在查询到数据后将key添加到布隆过滤器中。
     * @param key 要查询的key
     * @return 查询到的数据,如果不存在则返回null
     */
    public String getData(String key) {
        // 检查布隆过滤器,如果key不存在,则直接返回null
        if (!bloomFilter.contains(key)) {
            return null;
        }

        // 从数据库查询数据
        String data = queryDatabase(key);
        // 如果查询到数据,且该key尚未在布隆过滤器中,则添加到布隆过滤器
        if (data != null && !bloomFilter.contains(key)) {
            bloomFilter.add(key);
        }
        return data;
    }

    /**
     * 模拟从数据库查询数据的方法。
     * 实际应用中,这里应该是数据库查询逻辑。
     * @param key 要查询的key
     * @return 查询到的数据
     */
    private String queryDatabase(String key) {
        // 这里模拟数据库查询,实际应用中应替换为数据库查询逻辑
        // 假设数据库中存在key对应的数据
        return "some data for " + key;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2380386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Feign异步模式丢失上下文问题

Feign异步模式丢失上下文问题 问题描述 当我们使用异步对我们代码进行操作优化时&#xff0c;代码中使用了RequestContextHolder去获取上下文的数据&#xff0c;当我们执行原来可以执行的业务时发现报了空指针异常或数据为空&#xff0c;这是为什么呢&#xff1f; 原理解释 …

【AWS入门】Amazon SageMaker简介

【AWS入门】Amazon SageMaker简介 [AWS Essentials] Brief Introduction to Amazon SageMaker By JacksonML 机器学习(Machine Learning&#xff0c;简称ML) 是当代流行的计算机科学分支技术。通常&#xff0c;人们在本地部署搭建环境&#xff0c;以满足机器学习的要求。 AWS…

MYSQL 故障排查与生产环境优化

目录 一.前置知识点 1. 案例需求 &#xff08;1&#xff09;mysql 常见故障解决 &#xff08;2&#xff09;mysql 性能优化 2.案例实施思路 &#xff08;1&#xff09;单库常见故障分析 &#xff08;2&#xff09;主从常见故障分析 &#xff08;3&#xff09;从几个不同…

解决使用@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss“, timezone = “GMT+8“)时区转换无效的问题

前言 对于一些时间的字段&#xff0c;我们从数据库查询出来通常需要转换后返回给前端展示&#xff0c;前端需要的格式一般为yyyy-MM-dd HH:mm:ss&#xff0c;可以通过JsonFormat注解来作转换和时区转换。 问题场景 原因 LocalDateTime类本身不带时区信息所以转换无效 解决办…

计算机网络概要

⽹络相关基础知识 协议 两设备之间使⽤光电信号传输信息数据 要想传递不同信息 那么⼆者ᳵ就需要约定好的数据格式 层 封装 继承 多态是计算机的性质 它们⽀持了软硬件分层的实现 同层协议可以ᳵ接通信 同层协议ᳵ不直接通信 是各⾃调⽤下层提供的结构能⼒完成通信 分层…

Word压缩解决方案

Word压缩解决方案&#xff1a;基于图片压缩的 .docx 优化实践 &#x1f4cc; 背景 在日常科研写作或项目文档整理中&#xff0c;Word 文档&#xff08;.docx&#xff09;往往因为插入大量高清图表、扫描图像、公式图等导致文件体积过大&#xff0c;或者毕业学位论文查重要求上…

TDengine 2025年产品路线图

TDengine OSS 之 2025 年年度路线图如下表所示。 季度功能2025Q1 虚拟表查询能力&#xff1a;REGEXP、GREATEST、LEAST、CAST 函数支持判断表达式、单行选择函数的其他列值、INTERP 支持插值时间范围存储能力&#xff1a;支持将查询结果写入超级表、超级表支持 KEEP 参数、STM…

Ubuntu服务器部署多语言项目(Node.js/Python)方式实践

Ubuntu服务器部署多语言项目&#xff08;Node.js/Python&#xff09;方式实践 服务器脚本运行方式命令行直接执行nohup后台执行进程 Screen概述安装基本操作命令启动 Screen退出当前会话&#xff08;不终止进程&#xff09;查看所有会话重连会话关闭会话 常用快捷键典型使用场景…

计算机网络 - 2.基础协议

1.TCP协议 1.TCP(Transmission Control Protocol):传输控制协议2.TCP协议是一种面向连接的、可靠的、 基于字节流的传输层通信协议 1.面向连接:两个使用TCP协议的应用(通常一个客户和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接2.可靠的 1.数据传输之前都要建立…

初识css,css语法怎样学好css以及常见问题与避坑

一、CSS 是什么&#xff1f; CSS&#xff08;Cascading Style Sheets&#xff09;是一种用于描述网页文档&#xff08;HTML 或 XML&#xff09;呈现样式的语言。它负责控制网页元素的视觉表现&#xff0c;如颜色、字体、布局等&#xff0c;使内容与展示分离。 二、CSS 语法结构…

Axure疑难杂症:垂直菜单展开与收回(4大核心问题与专家级解决方案)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:垂直菜单展开与收回 主要内容:超长菜单实现、展开与收回bug解释、Axure9版本限制等问题解…

vue2.0 组件生命周期

个人简介 &#x1f468;‍&#x1f4bb;‍个人主页&#xff1a; 魔术师 &#x1f4d6;学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全栈发展 &#x1f6b4;个人状态&#xff1a; 研发工程师&#xff0c;现效力于政务服务网事业 &#x1f1e8;&#x1f1f3;人生格言&…

在Linux服务器上部署Jupyter Notebook并实现ssh无密码远程访问

Jupyter notebook版本7.4.2&#xff08;这个版本AI提示我Jupyter7&#xff08;底层是 jupyter_server 2.x&#xff09; 服务器开启服务 安装Jupyter notebook 7.4.2成功后&#xff0c;终端输入 jupyter notebook --generate-config 这将在 ~/.jupyter/ 目录下生成 jupyter_…

GPU 超级节点:AWS Trainium2 UltraServer

目录 文章目录 目录时间线Inferentia1Trainium1Inferentia2Trainium2Trainium2 ServerTrainium2 UltraServerTrainium2 UltraClustersTrainium3AWS GPU 实例矩阵与竞品分析SuperNode RackTrn2 ServerTrn2U Server ScaleUp 网络PCIe Gen5&#xff1a;CPU-Trainium2 ScaleUpNeuro…

git仓库中.git 文件很大,怎么清理掉一部分

查询 .git 文件大小&#xff0c;在 git-bash 里执行&#xff08;后面有些命令不能执行&#xff0c;也请在 git-bash 里执行&#xff09; windows11 安装好后右键没有 git bash 命令-CSDN博客 du -sh .git // 592m .git 操作前最好先备份一份&#xff0c;避免推送到远程时出错…

MySQL安装实战指南:Mac、Windows与Docker全平台详解

MySQL作为世界上最流行的开源关系型数据库&#xff0c;是每位开发者必须掌握的基础技能。本指南将手把手带你完成三大平台的MySQL安装&#xff0c;从下载到配置&#xff0c;每个步骤都配有详细说明和截图&#xff0c;特别适合新手学习。 一、Mac系统安装MySQL 1.1 通过Homebre…

Rocky Linux 远程服务器画面GUI传输到本地显示教程——Xming

Rocky Linux 远程服务器画面GUI传输到本地显示教程——Xming 下载Xming安装Xming安装Xming字体Xming的使用设置测试 Xming可以提供GUI环境&#xff0c;在Linux服务器上执行GUI应用时&#xff0c;可通过Xming在Windows上执行GUI操作。 下载Xming 下载链接&#xff1a;https://…

游戏引擎学习第283天:“让‘Standing-on’成为一个更严谨的概念

如果同时使用多个OpenGL上下文&#xff0c;并且它们都有工作负载&#xff0c;GPU或GPU驱动程序如何决定调度这些工作&#xff1f;我注意到Windows似乎优先处理活动窗口的OpenGL上下文&#xff08;即活动窗口表现更好&#xff09;&#xff0c;挺有意思的…… 当多个OpenGL上下文…

React集成百度【JSAPI Three】教程(001):快速入门

文章目录 1、快速入门1.1 创建react项目1.2 安装与配置1.3 静态资源配置1.4 配置百度地图AK1.5 第一个DEMO1、快速入门 JSAPI Three版本是一套基于Three.js的三维数字孪生版本地图服务引擎,一套引擎即可支持2D、2.5D、3D全能力的地理投影与数据源加载,帮助开发者轻松搞定平面…

python学习day2

今天主要学习了变量的数据类型&#xff0c;以及如何使用格式化符号进行输出。 一、认识数据类型 在python里为了应对不同的业务需求&#xff0c;也把数据分为不同的类型。 代码如下&#xff1a; """ 1、按类型将不同的变量存储在不同的类型数据 2、验证这些…