SpringBoot+Redis如何实现布隆过滤器
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,小编给大家分享一下SpringBoot+Redis如何实现布隆过滤器,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!简述关于布隆过滤器的详细介绍,我在这里就不再赘述一遍了我们首先知道:
千家信息网最后更新 2025年01月25日SpringBoot+Redis如何实现布隆过滤器
小编给大家分享一下SpringBoot+Redis如何实现布隆过滤器,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
简述
关于布隆过滤器的详细介绍,我在这里就不再赘述一遍了
我们首先知道:BloomFilter使用长度为m bit的字节数组,使用k个hash函数,增加一个元素: 通过k次hash将元素映射到字节数组中k个位置中,并设置对应位置的字节为1。查询元素是否存在: 将元素k次hash得到k个位置,如果对应k个位置的bit是1则认为存在,反之则认为不存在。
Guava 中已经有具体的实现,而在我们实际生产环境中,本地的存储往往无法满足我们实际的 需求。所以在这时候,就需要我们使用 redis 了。
Redis 安装 Bloom Filter
git clone https://github.com/RedisLabsModules/redisbloom.gitcd redisbloommake # 编译vi redis.conf## 增加配置loadmodule /usr/local/web/redis/RedisBloom-1.1.1/rebloom.so##redis 重启#关闭./redis-cli -h 127.0.0.1 -p 6379 shutdown#启动./redis-server ../redis.conf &
基本指令
#创建布隆过滤器,并设置一个期望的错误率和初始大小bf.reserve userid 0.01 100000#往过滤器中添加元素bf.add userid 'sbc@163.com'#判断指定key的value是否在bloomfilter里存在,存在:返回1,不存在:返回0bf.exists userid 'sbc@163.com'
结合 SpingBoot
搭建一个简单的 springboot 框架
方式一
配置
4.0.0 com.bloom test-bloomfilter 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.5.8.RELEASE org.springframework.boot spring-boot-starter org.apache.commons commons-lang3 3.0.1
redis本身对布隆过滤器就有一个很好地实现,在 java 端,我们直接导入 redisson 的 jar包即可
org.redisson redisson 3.8.2
将 Redisson实例 注入 SpringIOC 容器中
@Configurationpublic class RedissonConfig { @Value("${redisson.redis.address}") private String address; @Value("${redisson.redis.password}") private String password; @Bean public Config redissionConfig() { Config config = new Config(); SingleServerConfig singleServerConfig = config.useSingleServer(); singleServerConfig.setAddress(address); if (StringUtils.isNotEmpty(password)) { singleServerConfig.setPassword(password); } return config; } @Bean public RedissonClient redissonClient() { return Redisson.create(redissionConfig()); }}
配置文件
redisson.redis.address=redis://127.0.0.1:6379redisson.redis.password=
最后测试我们的布隆过滤器
@SpringBootApplicationpublic class BloomApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BloomApplication.class, args); RedissonClient redisson = context.getBean(RedissonClient.class); RBloomFilter bf = redisson.getBloomFilter("test-bloom-filter"); bf.tryInit(100000L, 0.03); Setset = new HashSet (1000); List list = new ArrayList (1000); //向布隆过滤器中填充数据,为了测试真实,我们记录了 1000 个 uuid,另外 9000个作为干扰数据 for (int i = 0; i < 10000; i++) { String uuid = UUID.randomUUID().toString(); if(i<1000){ set.add(uuid); list.add(uuid); } bf.add(uuid); } int wrong = 0; // 布隆过滤器误判的次数 int right = 0;// 布隆过滤器正确次数 for (int i = 0; i < 10000; i++) { String str = i % 10 == 0 ? list.get(i / 10) : UUID.randomUUID().toString(); if (bf.contains(str)) { if (set.contains(str)) { right++; } else { wrong++; } } } //right 为1000 System.out.println("right:" + right); //因为误差率为3%,所以一万条数据wrong的值在30左右 System.out.println("wrong:" + wrong); //过滤器剩余空间大小 System.out.println(bf.count()); }}
以上使我们使用 redisson 的使用方式,下面介绍一种比较原始的方式,使用lua脚本的方式
方式二
bf_add.lua
local bloomName = KEYS[1]local value = KEYS[2]local result = redis.call('BF.ADD',bloomName,value)return result
bf_exist.lua
local bloomName = KEYS[1]local value = KEYS[2] local result = redis.call('BF.EXISTS',bloomName,value)return result
@Servicepublic class RedisBloomFilterService { @Autowired private RedisTemplate redisTemplate; //我们依旧用刚刚的那个过滤器 public static final String BLOOMFILTER_NAME = "test-bloom-filter"; /** * 向布隆过滤器添加元素 * @param str * @return */ public Boolean bloomAdd(String str) { DefaultRedisScriptLuaScript = new DefaultRedisScript (); LuaScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("bf_add.lua"))); LuaScript.setResultType(Boolean.class); //封装传递脚本参数 List params = new ArrayList (); params.add(BLOOMFILTER_NAME); params.add(str); return (Boolean) redisTemplate.execute(LuaScript, params); } /** * 检验元素是否可能存在于布隆过滤器中 * @param id * @return */ public Boolean bloomExist(String str) { DefaultRedisScript LuaScript = new DefaultRedisScript (); LuaScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("bf_exist.lua"))); LuaScript.setResultType(Boolean.class); //封装传递脚本参数 ArrayList params = new ArrayList (); params.add(BLOOMFILTER_NAME); params.add(String.valueOf(str)); return (Boolean) redisTemplate.execute(LuaScript, params); }}
最后我们还是用上面的启动器执行测试代码
@SpringBootApplicationpublic class BloomApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BloomApplication.class, args); RedisBloomFilterService filterService = context.getBean(RedisBloomFilterService.class); Setset = new HashSet (1000); List list = new ArrayList (1000); //向布隆过滤器中填充数据,为了测试真实,我们记录了 1000 个 uuid,另外 9000个作为干扰数据 for (int i = 0; i < 10000; i++) { String uuid = UUID.randomUUID().toString(); if (i < 1000) { set.add(uuid); list.add(uuid); } filterService.bloomAdd(uuid); } int wrong = 0; // 布隆过滤器误判的次数 int right = 0;// 布隆过滤器正确次数 for (int i = 0; i < 10000; i++) { String str = i % 10 == 0 ? list.get(i / 10) : UUID.randomUUID().toString(); if (filterService.bloomExist(str)) { if (set.contains(str)) { right++; } else { wrong++; } } } //right 为1000 System.out.println("right:" + right); //因为误差率为3%,所以一万条数据wrong的值在30左右 System.out.println("wrong:" + wrong); }}
相比而言,个人比较推荐第一种,实现的原理都是差不多,redis 官方已经为我封装好了执行脚本,和相关 api,用官方的会更好一点
看完了这篇文章,相信你对"SpringBoot+Redis如何实现布隆过滤器"有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!
过滤器
布隆
元素
数据
方式
次数
脚本
测试
个位
字节
封装
配置
万条
参数
大小
官方
实际
数组
篇文章
误差
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
Apache服务器安全缺陷
热点网络安全密钥不正确
服务器一般都用来干嘛
数据库怎么实时json
数据库表 都代表什么意思
我的世界服务器记分板怎么做好看
网络安全战略有关专家论点
达思数据库恢复软件
神华软件开发
逆水寒二周年服务器转服
服务器现存问题
新建数据库排序规则怎么选
奇智岛软件开发有限公司
域名服务器的设置及管理
专家谈网络安全标准
福建南鼎网络技术
数据库论文摘要
纺织业互联网科技
天津市安全局网络安全行动
junit 数据库
seer数据库筛选
问道手游服务器登录不上怎么办
逸风公司是一家游戏软件开发商
湖北服务器机柜定制价格
监控系统的软件开发成本
关于软件开发免税
南京服务器托管有什么用
饥荒联机版买皮肤连接不上服务器
贵州晴风网络技术服务有限公司
专家谈网络安全标准