布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否可能存在于一个集合中。它通过使用多个哈希函数和一个位数组来表示一个集合,当一个元素被加入到集合时,通过哈希函数计算出多个哈希值,并将对应的位数组位置置为1。当需要检查一个元素是否存在于集合时,同样通过哈希函数计算出多个哈希值,如果所有对应的位数组位置都为1,则认为元素可能存在于集合中,如果有任何一个位置为0,则可以确定元素肯定不存在于集合中。
1. 定义布隆过滤器
布隆过滤器具有高效的插入和查询性能,且占用内存较小,但是存在一定的误判率,即可能会将不存在于集合中的元素误判为存在于集合中。
所以我们需要配置布隆过滤器的存储元素数量和误判率
![](https://file.jishuzhan.net/article/1789975518892789761/77e291afcc71c8c06853d1181b387c63.webp)
2.构造器注入布隆过滤器
在业务层里面注入布隆过滤器对象
![](https://file.jishuzhan.net/article/1789975518892789761/01cff1d875356198aa38c646f5a3ff96.webp)
3.判断用户名是否存在
当我们注册用户名时,可能之前被别人注册过了,这时我们需要先判断一下,在布隆过滤器中,是否已存在相同的用户名
调用布隆过滤器中的 contains() 方法判断
![](https://file.jishuzhan.net/article/1789975518892789761/ef9c7abefa659428a930c468604efc71.webp)
4.注册用户
在业务层中,定义一个注册方法,把前端请求的注册请求体传进去
第一步,就是获取到请求体中的 username 字段,然后调用判断用户名是否存在的方法,如果存在,就抛出异常
![](https://file.jishuzhan.net/article/1789975518892789761/dab5e32f21627a8bbf8026a9a3df1825.webp)
第二步,如果用户名不存在,也就是之前没有被注册过,那用户就可以继续注册了
然后就可以把请求体插入到数据库中
![](https://file.jishuzhan.net/article/1789975518892789761/cb34abeceb9a864d75fb524151dd3f2e.webp)
如果数据库中插入失败,就抛出异常
如果插入成功,就需要把注册的用户名给添加到布隆过滤器中,这样我们之后再判断数据库中是否存在已注册的用户名时,就不用访问数据库了,而是先在布隆过滤器中查找,这样减轻了对数据库的压力
5.分布式锁
如果用户名没注册,那么在布隆过滤器中就不存在该用户名,也就意味着可以触发注册流程插入数据库。但是如果产生恶意请求,在短时间内海量用户请求注册同一个用户名,这些请求都会落到数据库,造成数据库访问压力。这里通过分布式锁,锁定用户名进行串行执行,防止恶意请求利用未注册用户名将请求打到数据库。
5.1注入redissonClient
RedissonClient是一个Java的Redis客户端,它提供了许多方便的功能和工具来与Redis数据库进行交互。通过RedissonClient,开发人员可以方便地操作Redis数据库,进行数据的存储、查询、更新和删除等操作。RedissonClient支持多种数据结构和功能,如分布式锁、分布式集合、分布式队列等
![](https://file.jishuzhan.net/article/1789975518892789761/cb565e30f4ed8de3ae8ee3c39fb5ce4e.webp)
5.2获取锁
定义一个常量名作为锁名
![](https://file.jishuzhan.net/article/1789975518892789761/47efac6d26b9a51a319985119563d023.webp)
然后将常量名和注册的用户名绑定,从而获取到分布式锁
![](https://file.jishuzhan.net/article/1789975518892789761/d579358253724970d23fac38ae35c89a.webp)
所以当海量用户注册同一个用户名时,只有一个用户可以获取到分布式锁,则把该用户注册的信息插入到数据库中,插入成功后,再把用户名添加到布隆过滤器里面。而其他没有获取到锁的用户,则抛出异常
![](https://file.jishuzhan.net/article/1789975518892789761/efb89e6436e7a2b8b286360c04ecc3b1.webp)