Redis 布隆过滤器

news2024/11/24 3:53:20

布隆过滤器

这一篇文章主要是记录布隆过滤器的使用和认识
主要参考了如下的blog
https://blog.csdn.net/weixin_42972832/article/details/131211665
他讲的还不错

简单的来说,布隆过滤器,实际上就像是一个集合,拿redis的key来举例来说,布隆过滤器的设置就是去过滤不属于redis key集合的key,这个方法还算挺有效的

原理初探

我理解到,布隆过滤器,底层就是利用hash函数

首先布隆过滤器一般是bitmap
传来一个key,通过几个hash函数,生成几个index的位置,
然后一个一个去查这几个index位置上的bitmap,是否都是1,如果都是1,那么就说明这个key存在于这个集合中,那我们就要放行

这里的算法其实应该是多种多样,但是万变不离其中,就是使用hash匹配
在这里插入图片描述

其实很好理解拉,不能懂!

问题

  • 误判的问题

这里学过hash函数的很容易想到,这里可能会发生hash碰撞,如果一个key,他刚好等于已经存在的key的hash的化,就会发生hash碰撞,这就是会发生误判的理由

但是可以知道的是,如果说,过滤之后不在集合里边,那么就说名集合里边一定没有这个key,这个原理大家基本都懂,hash一般是不可逆的,
布隆过滤器: 不存在一定不存在,存在有可能存在,有可能不存在,有误判的可能

  • 不能删除的问题

因为布隆过滤器底层是多个hash共享数组的位置的,所以如果说,我们要删除某个key的化,就会影响到别人,所以布隆过滤器就是不能删除,只能重构

由于重构引出的问题就是,有可能重构的成本太大了,你有1亿条数据要重构,这成本太高了

手动实现

我这里的手动实现也是参考他的博客来看的,算是最简单的

先来看工具类

import com.hmdp.filter.BloomFilterInit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class CheckUtils {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 布隆过滤器校验
     *
     * @param key
     * @return boolean
     * @author hc
     * @date 2023/6/15 11:42
     */
    public boolean checkData(String key) {
        int abs = Math.abs(key.hashCode());
        long index = (long) (abs % Math.pow(2, 32));
        return redisTemplate.opsForValue().getBit(BloomFilterInit.WHITELIST_USER_KRY, index);
    }

    /**
     * 获取偏移量
     * @param key
     * @return long
     * @author hc
     * @date 2023/6/15 17:19
     */
    public long getOffsetId(String key) {
        int abs = Math.abs(key.hashCode());
        return getIndex(abs);
    }

    /**
     * 计算偏移量
     *
     * @param abs
     * @return java.lang.Long
     * @author hc
     * @date 2023/6/15 16:25
     */
    public long getIndex(int abs) {
        if (0 == abs) {
            return 0L;
        }
        return (long) (abs % Math.pow(2, 32));
    }
}

因为这里使用最简单的方法,所以直接就用java的hashCode方法得到hash值,然后这里的bitmap 我的容量大小是2的32次方

看这个工具类,也很好理解
生成index,就是hash值 % 2 ^32

就是这里的checkData比较特殊一点,先是获得index的位置,然后去redis中的bitmap中查找,如果有返回true,没有返回false

controller 测试类

@RestController
@RequestMapping("/bloom")
public class BloomFilterController {

    @Autowired
    private BloomFilterService bloomFilterService;

    @GetMapping("/add")
    public void addUser(String phone) {
        bloomFilterService.addUser(phone);
    }

    @GetMapping("/query/{id}")
    public void queryUser(@PathVariable Long id) {
        bloomFilterService.queryUser(id);
    }
}

一个添加用户
一个查用户

public interface BloomFilterService {
    void addUser(String phone);

    User queryUser(Long id);
}

实现类

@Slf4j
@Service
public class BloomFilterServiceImpl implements BloomFilterService {

    private static final String CACHE_KEY_USER = "user:";

    @Resource
    private CheckUtils checkUtils;
    @Resource
    private RedisTemplate redisTemplate;

    @Autowired
    private IUserService userService;

    @Autowired
    private RedisCache redisCache;

    public void addUser(String phone) {
        //返回id
        User user = BeanUtil.copyProperties(UserDTO.builder().nickName("").build(), User.class);

        userService.save(user.setPhone(phone));

        // 这里可以开启一个异步线程,在事务提交之后再进行操作
        if (user.getId() > 0) {
            String key = CACHE_KEY_USER + String.valueOf(user.getId());

            //计算index位置
            long index = checkUtils.getOffsetId(key);

            // redis的数据都需要使用统一的json工具转成json格式后放入
            redisCache.setCacheObject(key,user);
            redisTemplate.opsForValue().setBit(BloomFilterInit.WHITELIST_USER_KRY, index, Boolean.TRUE);
            log.info("新增用户信息|用户key:{}|布隆过滤器偏移量:{}", key, index);
        }
    }

    public User queryUser(Long id) {
        if (id < 0) {
            log.info("获取用户信息|用户id异常,异常id:{}", id);
            return null;
        }

        String key = CACHE_KEY_USER.concat(String.valueOf(id));
        boolean checkData = checkUtils.checkData(key);
        if (!checkData) {
            log.info("获取用户信息|用户id不存在,异常id:{}", id);
            return null;
        }

        //布尔过滤通过了!
        User user = redisCache.getCacheObject(key);
        log.info("用户信息 {}",user);

        //如果他为空
        if(Objects.isNull(user)) {
            return null;
        }
        return user;
    }

}

我来先说这里的addUser的逻辑

首先是直接到数据库中,存数据,这里的数据库的操作,可以自行换一个数据库,只要有id的就行

然后就是存redis的过程
先是获得redis的key 这里的key 拼接是这样 user: + id
然后是获得index的位置,这个也是bitmap中的index

存redis user用户
存redis bitmap 设置为1

queryUser

先是获得key,先去查布隆过滤器,布隆过滤器的checkData
这里的查找也是和设置bitmap的时候也是一样,就是去查找bitmap 在index位置是否是1
如果通过,说明集合里边有他,就说明成功

测试

先添加用户
在这里插入图片描述

redis的样子
在这里插入图片描述
然后我们去查1017是否存在

在这里插入图片描述

在这里插入图片描述
从这里看是存在的

我们再去查1000
是否存在
在这里插入图片描述
在这里插入图片描述
这样就实现了简单的布隆过滤器

总结

总结来看,我这个小布隆过滤器,只有2^32个位置,而且还只是看一位的,所以蛮粗糙的,但是不妨碍我们理解布隆过滤器,不管他多复杂,思想都是一样的,都要去做hash的运算,算位置,比较位置,就没了

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

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

相关文章

5、混合模型(Hybrid Models)

将两个预测模型的优势结合起来。 文章目录 1、简介2、组件和残差3、混合预测与残差3.1设计混合模型4、示例 - 美国零售销售1、简介 线性回归擅长推断趋势,但不能学习交互。XGBoost擅长学习交互,但不能推断趋势。在这个课程中,我们将学习如何创建"混合"预测器,这…

分割头篇 | 原创自研 | YOLOv8 更换 SEResNeXtBottleneck 头 | 附详细结构图

左图:ResNet 的一个模块。右图:复杂度大致相同的 ResNeXt 模块,基数(cardinality)为32。图中的一层表示为(输入通道数,滤波器大小,输出通道数)。 1. 思路 ResNeXt是微软研究院在2017年发表的成果。它的设计灵感来自于经典的ResNet模型,但ResNeXt有个特别之处:它采用…

BeanFactory创建过程(基于Servlet)

BeanFactory创建过程&#xff08;基于Servlet&#xff09; 1. 概述1.2 那么问题就来了1.2.1 谁负责AnnotationConfigServletWebServerApplicationContext实例呢&#xff1f;1.2.2 ApplicationContextFactory初始化过程又是怎么样的&#xff1f; 1.3 总结 2. 最后 1. 概述 Anno…

【C++零散小记录】类中重载返回类型为常量引用和非常量引用的函数

#include <iostream>class hyp { public://这里后面必须要加上const修饰符&#xff0c;否则这两个test函数不能重载int const& test() const{std::cout << "const" << std::endl;return num;}//int &test()//{// std::cout << &qu…

吉大计网笔记

Osi七层模型 物理层&#xff1a;比特流的透明传输 数据链路层&#xff1a;ip数据包装成帧并传输&#xff0c;处理相邻节点的数据传输。 网络层&#xff1a;选择路由和交换节点&#xff0c;处理任意节点的数据传输。 运输层&#xff1a;主机进程的数据传输服务&#xff0c;端到端…

雷达DoA估计的跨行业应用--麦克风阵列声源定位(Matlab仿真)

一、概述 麦克风阵列&#xff1a; 麦克风阵列是由一定数目的声学传感器&#xff08;麦克风&#xff09;按照一定规则排列的多麦克风系统&#xff0c;而基于麦克风阵列的声源定位是指用麦克风拾取声音信号&#xff0c;通过对麦克风阵列的各路输出信号进行分析和处理&#xff0c;…

Kubernetes实战(二十一)-event事件持久化

默认情况下&#xff0c; K8S 会将事件保留在 etcd 中一个小时&#xff0c;超过1小时的事件将无法看到&#xff0c;所以 K8S 默认保留事件的时间不足以来更深入的了解集群&#xff0c;所以将事件导出到集群外存储是有必要的&#xff0c;以实现可观测性和告警。 Event事件持久化…

央视见证|“看见中国汽车”走进首家汽车供应链企业东软睿驰

由工业和信息化部支持指导&#xff0c;中国汽车工业协会和央视网联合出品的2023《看见中国汽车》专题东软睿驰篇正式上线&#xff0c;记录品牌向上专项行动走进首家汽车供应链企业&#xff0c;展示东软睿驰围绕“成为OEM 软件定义汽车时代最可信赖的合作伙伴”核心战略的创新发…

IT行业证书大揭秘:哪些证书含金量最高?

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f4d2; 证书 &#x1f4d2; &#x1f4d6; 介绍 &#x1f4d6; 在IT行业&#xff0c;有许多证书被认为是含金量高的&#xff0c;可以帮助个人在职业发展中取得重要的竞争优势。以下是一些IT行业中被认为含金量高的证书&#x…

信用飞品牌升级——全方位优化用户体验 更周到更暖心

在当今社会,金融科技的迅速发展让信贷服务变得更加便捷。信贷品牌的崛起和发展,正在改变着人们的金融生活。消费者在选择信贷服务时,不仅仅关注信贷的额度和利率,服务体验也成为了一大关注点。一个优秀的信贷品牌,不仅要能满足用户的基本信贷需求,更要在服务体验上赢得用户的认…

基于 Echarts 的 Python 图表库:Pyecahrts交互式的日历图和3D柱状图

文章目录 概述一、日历图和柱状图介绍1. 日历图基本概述2. 日历图使用场景3. 柱状图基本概述4. 柱状图使用场景 二、代码实例1. Pyecharts绘制日历图2. Pyecharts绘制2D柱状图3. Pyecharts绘制3D柱状图 总结 概述 本文将引领读者深入了解数据可视化领域中的两个强大工具&#…

【2024全网最详细】Google 搜索命令终极指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 你是否尝试过使用 Google 搜索作为免费的 SEO …

【解刊】审稿人极其友好!中科院2区SCI,3个月录用,论文质量要求宽松!

计算机类 • 高分快刊 今天带来Springer旗下计算机领域高分快刊&#xff0c;有投稿经验作者表示期刊审稿人非常友好&#xff0c;具体情况一起来看看下文解析。如有投稿意向可重点关注&#xff1a; 01 期刊简介 Complex & Intelligent Systems ✅出版社&#xff1a;Sprin…

“互联网+水务”——智慧水务2.0推动水务行业产业结构变革

结合国内外水务企业数字化经典实践&#xff0c;探讨智慧水务2.0发展趋势&#xff0c;思考未来“标准体系数字资产使能技术”数字水务的发展态势&#xff0c;为我国水务企业制定和实施有效的数字化转型战略提供参考和借鉴。 通过数据清洗工作&#xff0c;识别并改善数据重复、数…

Linux useradd、gpasswd、chmod 等关于用户及权限设置

创建用户 useradd zen01 useradd zen02 useradd zen03 创建组 groupadd dev-group 把用户添加到dev-group组中 gpasswd -a zen01 dev-group gpasswd -a zen02 dev-group gpasswd -a zen03 dev-group 查看 dev-group组中用户列表 grep ‘dev-group’ /etc/group 创建文件 mkdir…

【go语言】error 错误处理详解

前言 在软件开发中&#xff0c;错误码是一种重要的信息传递方式&#xff0c;对于开发者和用户都具有重要的意义。一般情况下&#xff0c;系统出现故障&#xff0c;由运维在狂轰滥炸的报警信息中找到关键错误信息和研发人员进行沟通&#xff0c;再查看代码逻辑理清问题根源&…

dolist案例实现

这段代码是一个使用Vue.js实现的简单的ToDoList&#xff08;待办事项列表&#xff09;应用。我们分几个部分详细解释这段代码。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>todolist</title&g…

算法练习01——哈希部分双指针

目录 1. 两数之和(*)242. 有效的字母异位词(easy)49. 字母异位词分组(*)349. 两个数组的交集202. 快乐数(1.使用Set存哈希&#xff0c;2.快慢指针)454. 四数相加 II383. 赎金信15. 三数之和*(双指针)18. 四数之和*(双指针)128. 最长连续序列 1. 两数之和(*) https://leetcode.…

Acwing---797.差分

差分 1.题目2.基本思想3.代码实现 1.题目 输入一个长度为 n n n 的整数序列。 接下来输入 m m m 个操作&#xff0c;每个操作包含三个整数 l , r , c l,r,c l,r,c&#xff0c;表示将序列中 [ l , r ] [l,r] [l,r] 之间的每个数加上 c c c。 请你输出进行完所有操作后的…

2024新利好!一文读懂Shopee 3PF PFF一店多运模式

2023年年底&#xff0c;Shopee平台又有大动作&#xff01;正式上线了3PF PFF一店多运模式&#xff0c;已完成库存管理模式升级的三方仓卖家&#xff0c;即可开启一店多运新模式。 图源&#xff1a;Shopee 一、3PF PFF模式优势解析 三方仓一店多运&#xff08;3PF PFF&#xf…