BloomFilter如何快速检查用户名重复

 更新时间:2025年04月19日 09:34:20   作者:埃泽漫笔  
这篇文章主要介绍了BloomFilter如何快速检查用户名重复问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

背景

在我们的项目中,用户名是不能重复的,因为在数藏项目中,用户名的唯一性很重要,因为藏品要做溯源,要确保整个链路上的参与者的唯一性,虽然用户 id 也是我唯一的,但是页面上展示的时候不能用 id 呀。

有些网站,比如淘宝网,也是要求用户名唯一的。

所以为了实现这个用户在注册,改名的时候的用户名的唯一性,我们一般是先从数据库查询是否存在,不存在则让用户注册。

但是为了考虑到性能,我们会把用户名存储到缓存中,一般使用 redis 缓存。

那既然都用了缓存了,那还不如干脆直接就用布隆过滤器来存储,既可以做重复校验,又能节省空间。所以,我们在用户名重复检验这里就用到了布隆过滤器。

简介

布隆过滤器是一种数据结构,用于快速检索一个元素是否可能存在于一个集合(bit 数组)中。

它的基本原理是利用多个哈希函数,将一个元素映射成多个位,然后将这些位设置为 1。当查询一个元素时,如果这些位都被设置为 1,则认为元素可能存在于集合中,否则肯定不存在。

所以,布隆过滤器可以准确的判断一个元素是否一定不存在,但是因为哈希冲突的存在,所以他没办法判断一个元素一定存在。只能判断可能存在。

代码实现

所以,我们定义了两个方法,nickNameExist用于判断是否存在,addNickName用于向布隆过滤器中添加已注册的用户名。

public boolean nickNameExist(String nickName) {
    //如果布隆过滤器中存在,再进行数据库二次判断
    if (this.bloomFilter.contains(nickName)) {
        return userMapper.findByNickname(nickName) != null;
    }

    return false;
}

private boolean addNickName(String nickName) {
    return this.bloomFilter.add(nickName);
}

这里nickNameExist方法,先从布隆过滤器中查询,如果如果查到了,再去数据库中查了一下,为啥呢?

因为布隆过滤器有误判的,存在一定的误判率,他会把不存在的用户判断为存在,所以当检查结果是存在的时候,需要再次判断一次。

因为用户注册的时候,大多数情况下都是不重复的,所以我们可以快速的用布隆过滤器进行不存在的判断。

这里的bloomFilter是这样被初始化出来的:

private RBloomFilter<String> bloomFilter;

@Override
public void afterPropertiesSet() throws Exception {
    this.bloomFilter = redissonClient.getBloomFilter("nickName");
    if (!bloomFilter.isExists()) {
        this.bloomFilter.tryInit(10000000L, 0.01);
    }
}

我们设置了10000000的容量,误判率是0.01。

然后在修改用户名这里,用这样的方式进行调用的。

如果用户名修改了怎么办?

如果原来用户名是Aizer,被放到布隆过滤器了,但是后面我改成 Aizer666了,那么意味着 Aizer已经没有了,那么如何从布隆过滤器删除呢?

很遗憾,不支持!

那怎么办呢?

其实问题也不大,因为布隆过滤器本身就存在误判率,但我们检查布隆过滤器发现存在的时候,还是会去数据库再确认一遍的。

只要我们定期的重建一下布隆过滤器就行了。重建就是都删了,然后重新构建。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解Java如何优雅地书写if-else

    详解Java如何优雅地书写if-else

    在日常开发中我们常常遇到有多个if else的情况,之间书写显得代码冗余难看,对于追求更高质量代码的同学,就会思考如何优雅地处理这种代码。本文我们就来探讨下几种优化if else的方法
    2022-08-08
  • Java中ScheduledExecutorService介绍和使用案例(推荐)

    Java中ScheduledExecutorService介绍和使用案例(推荐)

    ScheduledExecutorService是Java并发包中的接口,用于安排任务在给定延迟后运行或定期执行,它继承自ExecutorService,具有线程池特性,可复用线程,提高效率,本文主要介绍java中的ScheduledExecutorService介绍和使用案例,感兴趣的朋友一起看看吧
    2024-10-10
  • spring batch 读取多个文件数据导入数据库示例

    spring batch 读取多个文件数据导入数据库示例

    本篇文章主要介绍了spring batch 读取多个文件数据导入数据库示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • java 设计模式之State(状态模式)

    java 设计模式之State(状态模式)

    这篇文章主要介绍了java 设计模式之State(状态模式)的相关资料,一个类的行为基于它的状态的改变而改变。状态模式归属于行为型模式,需要的朋友可以参考下
    2017-08-08
  • 教你开发脚手架集成Spring Boot Actuator监控的详细过程

    教你开发脚手架集成Spring Boot Actuator监控的详细过程

    这篇文章主要介绍了开发脚手架集成Spring Boot Actuator监控的详细过程,集成包括引入依赖配置文件及访问验证的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • 解决异常处理问题:getReader() has already been called for this

    解决异常处理问题:getReader() has already been called for this

    这篇文章主要介绍了解决异常处理:getReader() has already been called for this问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 微信公众号开发之回复图文消息java代码

    微信公众号开发之回复图文消息java代码

    这篇文章主要为大家详细介绍了微信公众号开发之回复图文消息java代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Java实现批量查找与替换Excel文本的思路详解

    Java实现批量查找与替换Excel文本的思路详解

    在 Java 中,可以通过find和replace的方法来查找和替换单元格的数据,下面小编将以Excel文件为例为大家介绍如何实现Excel文件内容的批量替换,感兴趣的朋友跟随小编一起看看吧
    2023-10-10
  • java如何实现项目启动时执行指定方法

    java如何实现项目启动时执行指定方法

    这篇文章主要为大家详细介绍了java项目如何启动时执行指定方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • SpringBoot整合ELK使用教程

    SpringBoot整合ELK使用教程

    对于一个运行中的应用来说,线上排查问题是一件很头疼的问题,不管是springboot单应用,还是springcloud微服务应用,一旦在生产环境出了问题,大多数人第一反应就是赶紧去看日志查问题,本文给大家介绍了SpringBoot整合ELK使用教程,需要的朋友可以参考下
    2024-11-11

最新评论