布隆过滤器的原理
其本质就是一个只包含0和1的数组。具体操作当一个元素被加入到集合里面后,该元素通过K个Hash函数运算得到K个hash后的值,然后将K个值映射到这个位数组对应的位置,把对应位置的值设置为1。查询是否存在时,我们就看对应的映射点位置如果全是1,他就很可能存在(跟hash函数的个数和hash函数的设计有关),如果有一个位置是0,那这个元素就一定不存在。
Redis 中的布隆过滤器
Redis 官方提供的布隆过滤器到了 Redis 4.0 提供了插件功能之后才正式登场。布隆过滤器作为一个插件加载到 Redis Server 中,给 Redis 提供了强大的布隆去重功能。
网上找一个原理
1.引入redisson依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.14.1</version> </dependency>
2.添加redisson config
package org.gz.risk.config; import org.redisson.Redisson; import org.redisson.config.Config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; /** * Redisson配置 */ @ConfigurationProperties( prefix = "spring.redis" ) @Configuration public class RedissonConfiguration { private String host; private String port; private String password; @Bean(destroyMethod="shutdown") Redisson redisson() throws IOException { String address = "redis://".concat(host).concat(":").concat(port); Config config = new Config(); config.useSingleServer().setAddress(address) .setConnectionPoolSize(30) .setConnectionMinimumIdleSize(10) .setPassword(password); return (Redisson) Redisson.create(config); } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getPort() { return port; } public void setPort(String port) { this.port = port; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
3.布鲁过滤器实现类
package org.gz.risk.auditing.service; import org.redisson.Redisson; import org.redisson.api.RBloomFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 布鲁过滤器实现类 * * @author Administrator * @date 2021-07-07 17:16 * @since 1.0.0 */ @Service public class BloomFilterService implements IBloomFilterService { /** * 容量 */ protected Long expectedInsertions = 1000000L; /** * 误差 */ protected Double falseProbability = 0.001; @Autowired private Redisson redisson; @Override public void add(String key , String data) { RBloomFilter bloomFilter = redisson.getBloomFilter(key); bloomFilter.tryInit(expectedInsertions, falseProbability); bloomFilter.add(data); } @Override public Boolean exist(String key , String data) { RBloomFilter bloomFilter = redisson.getBloomFilter(key); bloomFilter.tryInit(expectedInsertions , falseProbability); boolean isExist = bloomFilter.contains(data); return isExist; } }
4.布鲁过滤器的接口
package org.gz.risk.auditing.service; /** * 布鲁过滤器Service接口类 * * @date 2021-07-07 17:14 * @since 1.0.0 */ public interface IBloomFilterService<T> { /** * 添加数据 * * @param key * @param data */ void add(String key , String data); /** * 判断是否存在 * * @param key * @param data * @return */ Boolean exist(String key , String data); }
5.单元测试
package org.gz.risk; import org.gz.risk.auditing.service.IBloomFilterService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; /** * @version 1.0 * @date 2021/7/8 15:13 */ @RunWith(SpringRunner.class) @SpringBootTest @TestPropertySource("classpath:bootstrap.properties") public class TestBloomFilterTest { @Autowired IBloomFilterService bloomFilterService; private static final String BOOLFILTER_KEY = "boolFilter:user"; @Test public void add(){ bloomFilterService.add(BOOLFILTER_KEY,"16987544"); //查询 Boolean f = bloomFilterService.exist(BOOLFILTER_KEY,"16987544"); System.out.println("【获取bloomFilter】="+f); } }
6.执行效果