算法技巧-布隆过滤器

布隆过滤器(英语:Bloom Filter)是1970年由一个叫布隆的小伙子提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

收录在算法技巧、数据结构、常见算法汇总

布隆过滤器原理

当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。

检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。

布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

布隆过滤器应用

  1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,上亿)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤(判断一个邮件地址是否在垃圾邮件列表中)、黑名单功能(判断一个 IP 地址或手机号码是否在黑名单中)等等。
  2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重、对巨量的 QQ 号/订单号去重。

去重场景也需要用到判断给定数据是否存在,因此布隆过滤器主要是为了解决海量数据的存在性问题。

布隆过滤器实践

下面基于redission客户端的redis布隆过滤器做简单实践。 redis配置

java 复制代码
@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://" + redisHost + ":" + redisPort);

        return Redisson.create(config);
    }
}

布隆过滤器配置

java 复制代码
@Service
public class BloomFilter {
    private final RedissonClient redissonClient;

    private RBloomFilter<String> bloomFilter;

    @Autowired
    public BloomFilter(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }


    @PostConstruct
    private void init() {
        bloomFilter = redissonClient.getBloomFilter("test");
        bloomFilter.tryInit(10000L, 0.01);
    }

    public boolean add(String key) {
        return bloomFilter.add(key);
    }

    public boolean contains(String key) {
        return bloomFilter.contains(key);
    }
}

测试用例

java 复制代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Slf4j
public class BloomFilterTest {

    @Resource
    private BloomFilter bloomFilter;

    @Test
    public void testBloomFilter() {
        boolean ret = bloomFilter.add("test1");
        log.info("testBloomFilter ret={}", ret);
        ret = bloomFilter.add("test2");
        log.info("testBloomFilter ret={}", ret);
        ret = bloomFilter.contains("test1");
        log.info("testBloomFilter ret={}", ret);
        ret = bloomFilter.contains("test2");
        log.info("testBloomFilter ret={}", ret);
    }
}

执行结果

txt 复制代码
2023-12-31 17:23:14.478|INFO |test|1|127.0.0.1|08f03f7f8b5c44bbad4c7962e6018b04|testBloomFilter ret=true|com.toby.dynamic.data.source.redis.BloomFilterTest
2023-12-31 17:23:14.478|INFO |test|1|127.0.0.1|08f03f7f8b5c44bbad4c7962e6018b04|testBloomFilter ret=true|com.toby.dynamic.data.source.redis.BloomFilterTest
2023-12-31 17:23:14.478|INFO |test|1|127.0.0.1|08f03f7f8b5c44bbad4c7962e6018b04|testBloomFilter ret=true|com.toby.dynamic.data.source.redis.BloomFilterTest
2023-12-31 17:23:14.478|INFO |test|1|127.0.0.1|08f03f7f8b5c44bbad4c7962e6018b04|testBloomFilter ret=true|com.toby.dynamic.data.source.redis.BloomFilterTest

参考
Redis BloomFilter布隆过滤器原理与实现
布隆过滤器
布隆过滤器

相关推荐
默 语5 分钟前
Records、Sealed Classes这些新特性:Java真的变简单了吗?
java·开发语言·python
王码码20358 分钟前
Go语言中的Elasticsearch操作:olivere实战
后端·golang·go·接口
斯内科9 分钟前
FFT快速傅里叶变换
算法·fft
zjshuster14 分钟前
墨西哥中央银行网联清算系统接入总结
java·财务对账
小锋java123415 分钟前
SpringBoot 4 + Spring Security 7 + Vue3 前后端分离项目设计最佳实践
java·vue.js·spring boot
一 乐15 分钟前
校园线上招聘|基于springboot + vue校园线上招聘系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·校园线上招聘系统
不懂的浪漫17 分钟前
mqtt-plus 架构解析(四):MqttMessageInterceptor 的扩展点设计
java·spring boot·物联网·mqtt
2301_8227032018 分钟前
开源鸿蒙跨平台Flutter开发:幼儿疫苗全生命周期追踪系统:基于 Flutter 的免疫接种档案与状态机设计
算法·flutter·华为·开源·harmonyos·鸿蒙
西海天际蔚蓝19 分钟前
AI配合写的第一个demo系统页面
java·人工智能
贵慜_Derek20 分钟前
Managed Agents 里,Harness 到底升级了什么?
人工智能·算法·架构