SpringBoot+Redis如何实现布隆过滤器
发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,小编给大家分享一下SpringBoot+Redis如何实现布隆过滤器,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!简述关于布隆过滤器的详细介绍,我在这里就不再赘述一遍了我们首先知道:
千家信息网最后更新 2024年11月20日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安全错误
数据库的锁怎样保障安全
ad域无法进入服务器管理器
消灭病毒2022服务器
cf进不了绿色服务器怎么办
收百度网络技术有限公司
和平精英低配版的服务器在哪
杭州兹华软件开发有限公司
it数据库和硬件的区别
大合网络技术开发有限公司
软件开发岗位主要负责什么
c语言怎么调用数据库
李朗软件园的软件开发企业
医工所的软件开发
互联网保险科技产业链
云服务器最好管理系统
学校网络安全的工作内容
2-99网络安全和信息化
cs架构服务器
一年级网络安全教育心得体会
linux 常用数据库
厦门总工会网络安全题目
华夏文明联机服务器
中国企业网络安全资讯
服务器端口服务启动
gdb格式的数据库如何打开
少年三国志化金数据库
我的世界解说开服务器
太原服务器内存
服务器磁盘可以修改吗
互联网科技服务是干嘛
2020年网络安全工作计划