大家好,我是哪吒。
布隆过滤器BloomFilter是什么?BlomFilter是布隆过滤器专门用来解决去重问题的高级数据结果。
本质是一个大型位数组和几个不同的无偏hash函数,这意味着分布均匀。它由一个初始值为零的bit数组和多个哈希函数组成,用来判断一个数据是否存在。它和Hyperloglog一样,不太准确,有一定的误判概率。
布隆过滤器BlomFilter能做什么?高效插入和查询占用空间少,返回结果不确定。如果一个元素被判断为存在,它就不一定存在;当它不存在时,它就不存在。
由于不同字符串的hashcode可能相同,布隆过滤器bloomfilter根据hashcode判断,如果hashcode存在,其对应的字符串不一定是您想要的字符串;但是,当hashcode不存在时,您想要的字符串肯定不存在,精品~
布隆过滤器BlomFilter只能添加元素,不能删除元素。
这与上述hashcode判断原理相同。同一hashcode的字符串将存储在index中。删除时,删除index。此时,可以删除具有相同hashcode的不同字符串和细品~
三、布隆过滤器使用场景1、解决缓存穿透问题一般情况下,先查询Redis缓存,如果Redis中没有Redis,再查询MySQL。当数据库中没有此数据时,每次查询都要访问数据库,即缓存穿透。
在Redis前添加一层布隆过滤器,请先在布隆过滤器中判断。如果布隆过滤器不存在,直接返回,不再询问Redis和MySQL。
在布隆过滤器中存在时,再访问Redis,再访问数据库。
缓存穿透问题的完美解决方案。
2、黑名单如果黑名单很大,数千万,储存空间很大,在布隆过滤器中实现黑名单功能是一个很好的选择。
3、网页爬虫去除URL,避免爬取相同的URL地址。4.操作布隆过滤器BloomFilter1、使用布隆过滤器(1)初始bitmapp布隆过滤器 本质上 是由长度为 m 位向量或位列表(仅包括) 0 或 1 由位值列表组成,最初的所有值都设置为 0。
(2)添加key使用多个hash函数对key进行hash操作,获得整数索引值,对位数组长度进行取模操作,获得位置,每个hash函数都会获得不同的位置,将这些位置的值置为1,表示添加成功。
比如我们加一个字符串“哪吒编程”,多次hash字符串(key) → 取模运行→ 得到坑位。
2、删除key只要其中一个是零,就意味着key不存在,但如果都是1,就不一定存在相应的key。
3、判断它是否存在查询布隆过滤器中是否存在key时,首先查询这个key key 通过相同的多个 hash 操作函数,检查相应位置是否为 1,
只要一个位置为零,就意味着布隆过滤器中的这个 key 不存在;
如果所有这些位置都是这样的话 1.这意味着它很有可能存在;
因为这些位置 1 也许是因为别的 key 由存在引起的,即上述hash冲突
五、代码实例1、使用Redis作为缓存
public class StudentSerivce { public static final String CACHE_KEY = "student:"; @Resource private StudentMapper studentMapper; @Resource private RedisTemplate redisTemplate; public void addstudent(Student student){ int i = studentMapper.insertStudent(student); if(i > 0) { //去数据库,重新获取新数据,做缓存 student=studentMapper.selectByKey(student.getId()); ///缓存key String key=CACHE_KEY+student.getId(); //成功插入mysql,然后从mysql查询。然后插入redis redisTemplate.opsForValue().set(key,student); } } public Student findstudentById(Integer studentId){ Student student = null; String key=CACHE_KEY+studentId; // 查询redis student = (Student) redisTemplate.opsForValue().get(key); // redis没有,查询mysql if(student==null){ // 从mysql中发现studentt student=studentMapper.selectByPrimaryKey(studentId); // mysql有,没有redis if (student != null) { // 在redisssql中写入mysql的数据 redisTemplate.opsForValue().set(key,student); } } return student; }}
2、布隆过滤器
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * 布隆过滤器 -> redis -> mysql * @autor 哪吒编程 * @date 2023-04-17 */@Servicepublic class StudentServiceImpl implements StudentService { public static final String CACHE_KEY = "student:"; @Autowired private StudentMapper studentMapper; @Autowired private RedisTemplate redisTemplate; public void addstudent(student student){ int i = studentMapper.insertSelective(student); if(i > 0) { //去数据库,重新获取新数据,做缓存 student=studentMapper.selectByPrimaryKey(student.getId()); ///缓存key String key=CACHE_KEY+student.getId(); ///成功插入mysql,然后从mysql查询,然后插入rediss redisTemplate.opsForValue().set(key,student); } } public student findstudentById(Integer studentId){ student student = null; ////缓存key的名字 String key=CACHE_KEY+studentId; // 查询redis student = (student) redisTemplate.opsForValue().get(key); ///redis没有,查询mysql if(student==null) { student=studentMapper.selectByPrimaryKey(studentId); // mysql有,没有redis if (student != null) { // 将mysql获得的数据写入rediss redisTemplate.opsForValue().set(key,student); } } return student; } /** * BloomFilter -> redis -> mysql * 白名单:whites */ public student findStudentByIdWithBloomFilter (Integer studentId) { student student = null; String key = CACHE_KEY + studentId; ///布隆过滤器校准,没有绝对没有,有可能有 if(!checkWithBloomFilter("whites",key)) { log.info(无此客户信息的白名单:{}key); return null; } ///查询redis student = (Student) redisTemplate.opsForValue().get(key); ///redis没有,查询mysql if (student == null) { student = studentMapper.selectByPrimaryKey(studentId); // mysql有,没有redis if (student != null) { // 将mysql获得的数据写入rediss redisTemplate.opsForValue().set(key, student); } } return student; } /** * 检查布隆过滤器是否存在 */ public boolean checkWithBloomFilter(String checkItem,String key) { int hashValue = Math.abs(key.hashCode()); long index = (long) (hashValue % Math.pow(2, 32)); return redisTemplate.opsForValue().getBit(checkItem, index); }}
六、总结
- 是的,可能有;没有,肯定没有;
- 使用Z时,初始化值尽可能满足实际元素长度,避免扩容;
- 当实际元素数量超过初始长度时,应重建布隆过滤器,然后批量添加所有历史元素;