Redis 布隆过滤器

布隆过滤器

这一篇文章主要是记录布隆过滤器的使用和认识
主要参考了如下的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的运算,算位置,比较位置,就没了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

static 成员函数

在书上看到这样一段话 ”在引入static 成员函数之前&#xff0c;C语言要求所有的成员函数都必须经由该 class 的对象来调用。而实际上&#xff0c;只有当一个或多个 nonstatic 数据成员在成员函数中被直接存取时&#xff0c;才需要 class 的对象。class 对象提供了 this 指针来…

C#版字节跳动SDK - SKIT.FlurlHttpClient.ByteDance

前言 在我们日常开发工作中对接第三方开放平台&#xff0c;找一款封装完善且全面的SDK能够大大的简化我们的开发难度和提高工作效率。今天给大家推荐一款C#开源、功能完善的字节跳动SDK&#xff1a;SKIT.FlurlHttpClient.ByteDance。 项目官方介绍 可能是全网唯一的 C# 版字…

C语言简介

Visual Studio编辑器左侧菜单栏不小心关掉如何打开&#xff08;左侧解决方案资源管理器不显示如何打开&#xff09;、C语言中int main和void main的区别以及C工程的创建_visual studio2022 资源管理器怎么打开桌面面板-CSDN博客 目录 ​编辑 1. 简介 2. 介绍 3. C程序 …

保姆式挑选钢化膜教程,不看真的后悔

覆盖率 我们怎样挑选钢化膜呢&#xff1f;选手机膜最重要的是看它的覆盖率&#xff0c;所谓覆盖就是手机膜覆盖住你的手机屏幕&#xff0c;一般覆盖率达到 97% 左右&#xff0c;几乎就感受不到膜的存在。 很多朋友应该听说过 2D 钢化膜&#xff0c;它是没有经过边缘抛光处理的…

Django部署到服务器后无法获取到静态元素 The requested resource was not found on this server

问题描述 写了一个Django项目&#xff0c;部署到云主机后&#xff0c;访问发现图片无法访问&#xff0c;报错The requested resource was not found on this server 图片是一个词云图&#xff0c;根据爬虫爬取的信息生成的&#xff0c;根据爬取的信息会改变&#xff0c;所以没…

负责任的老师都具备哪些特点

选择成为一名教师时&#xff0c;就承诺要为学生提供最好的教育。但是&#xff0c;什么是最好的教育呢&#xff1f;我认为&#xff0c;一个负责任的老师应该具备以下几个特点&#xff1a; 了解学生 作为老师&#xff0c;我们首先要了解自己的学生。每个学生都是独特的个体&…

研究近期的伦敦银走势图 有什么特别要注意的?

对伦敦银走势图进行分析&#xff0c;这是我们入场交易之前要做的必要准备。没有对伦敦银走势图的充分分析和了解&#xff0c;投资者不应该入场。下面我们就来讨论一下&#xff0c;要对近期的伦敦银走势图进行分析&#xff0c;我们要注意什么。 研究美联储的动向。从上周开始&am…

UE4 C++ UGameInstance实例化

1.创建GameInstance C类 2.在.h添加变量 class 工程名称_API UMyGameInstance : public UGameInstance {GENERATED_BODY()public: //定义了三个公开的变量UMyGameInstance();UPROPERTY(EditAnywhere, BlueprintReadWrite, Category "MyGameInstance")FString Name…

回归预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小二乘支持向量机多变量回归预测

回归预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小二乘支持向量机多变量回归预测 目录 回归预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小二乘支持向量机多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现CPO-LSSVM冠豪猪算法优化最小二乘支持向…

HarmonyOS4.0系统性深入开发33相对布局(RelativeContainer)

相对布局&#xff08;RelativeContainer&#xff09; 概述 RelativeContainer为采用相对布局的容器&#xff0c;支持容器内部的子元素设置相对位置关系。子元素支持指定兄弟元素作为锚点&#xff0c;也支持指定父容器作为锚点&#xff0c;基于锚点做相对位置布局。下图是一个…

python数据类型-列表

1 python中列表的定义 python中列表是一种有序和可更改的集合&#xff0c;允许重复的成员&#xff0c;列表中的元素之间数据类型可以不同&#xff08;元素之间数据类型可以不相同&#xff0c;这一点和其它的面向对象的开发语言有很大的不同&#xff0c;如C#、Java&#xff09;…

如何本地搭建Emby影音管理服务并结合内网穿透实现远程访问本地影音库

文章目录 1.前言2. Emby网站搭建2.1. Emby下载和安装2.2 Emby网页测试 3. 本地网页发布3.1 注册并安装cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar内网穿透本地设置 4.公网访问测试5.结语 1.前言 在现代五花八门的网络应用场景中&#xff0c;观看视频绝对是主力应用场景之一&…

【Midjourney】新手指南:命令

1./ask 向Midjourney提问&#xff0c;不过问题和回答都是英文的&#xff0c;例如&#xff1a; 2./blend 将两张图片合并为一张 ​ 3./describe 上传一张图片&#xff0c;Midjourney会生成四组该图片相关的关键词&#xff0c;可以使用这些关键词再生成图片。 ​ 4./turbo …

qt 控件比较大,图像比较小时,如何居中贴图

直接用样式表修改 QPushButton#close_btn { background:transparent; background-image: url(://res/image/close_white.png); background-repeat: no-repeat; background-position: center;}

Linux系统安全之iptables防火墙

目录 一、iptables防火墙的基本介绍 1、netfile与iptables的关系 1.1netfile 1.2iptables 1.3iptables是基于内核的防火墙&#xff0c;其中内置了raw&#xff0c;mangle&#xff0c;nat和filter四个规则表 2、iptables防火墙默认规则表&#xff0c;链结构 二、iptables的…

Go之流程控制大全: 细节、示例与最佳实践

本文深入探讨Go语言中的流程控制语法&#xff0c;包括基本的if-else条件分支、for循环、switch-case多条件分支&#xff0c;以及与特定数据类型相关的流程控制&#xff0c;如for-range循环和type-switch。文章还详细描述了goto、fallthrough等跳转语句的使用方法&#xff0c;通…

gradio进度条实现不成功,使用components替代

实现了一个功能&#xff0c;上传一个图像后自动调用函数做算法处理&#xff0c;但是网页如果静止&#xff0c;等待的这段时间会令人怀疑&#xff0c;是不是真的在处理&#xff0c;处理的时长是多少&#xff1f; 首先查了下进度条的实现&#xff0c;有个Progress的函数&#xf…

什么是高级持续性威胁(APT)

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle O…

【Unity3D小功能】Unity3D中Text使用超链接并绑定点击事件

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中遇到了要给Text加超链接的需求&#xff0c;研究了实现…

C++开发基础之预编译头文件 stdafx.h的作用

引言 在 C 开发中&#xff0c;为了提高编译效率和减少重复编译的时间&#xff0c;我们可以使用 stdafx.h 这个预编译头文件。本文将介绍 stdafx.h 是什么&#xff0c;以及它在 C 项目中的作用。 1、什么是 stdafx.h&#xff1f; stdafx.h 是一个预编译头文件&#xff0c;在 …