布隆过滤器

了解

  1. 1970年,由Bloom 提出的
  2. 二进向量(位数组)随机映射函数组成映射关系
  3. BitSet 作为位容器(位数组),位值为 0 或者 1
  4. 随机映射函数(HashFunction),目的生成一个对应的数值,然后存入到 BitSet中。
  5. 优点:
    1. 数组容器占用空间小。存储100W个数据,占 122 KB(100W*1bit/8/1024)
    2. 如果存储过数据,容器必定有痕迹
  6. 缺点:
    1. 容器有痕迹的,不一定存储过数据
    2. 容器中只能添加数据,不能删除数据。删除元素导致位值的变化,会提高容器的错误率
    3. 数据量越大,错误率会越高。所以一般 位容器的初始位数会很大

注 : 1 M = 1024 KB = 1024 * 1024 B(byte) = 1024 * 1024 * 8 bit

原理

image

添加对象

被添加的对象,通过 HashFunction 会生产一个或多个对应的数值,并存储到 BitSet 容器中。BitSet 中位值会由 0->1 ,多个对象存储时,位值也只会存储到 1。

判断对象

判断的过程中,实际是看对象通过 HashFunction 所生产的一个或多个对应的数值,在 BitSet 中的位值是否都为1
图中,对象4 对应的所有位值里面,存在一个值为 0,则 对象4 一定没存储过。

实现

/** * 布隆过滤器 * * @author ZZ_C * */ public class TestBloomFilter { /** * 一个长度为10亿的位 */ private static int DEFAULT_SIZE = 256 << 22; /** * 为了降低错误率,使用hash算法,定义8个不同的质数 */ private static final int[] seeds = { 3, 5, 7, 11, 13, 17, 19, 23 }; /** * 定义seeds.length 个 hash 函数用于哈希计算 */ private static HashFunction[] functions = new HashFunction[seeds.length]; /** * 布隆过滤器的核心容器,初始化,定义了 10 亿个位 */ private static BitSet bitSet = new BitSet(DEFAULT_SIZE); TestBloomFilter() { for (int i = 0; i < seeds.length; i++) { functions[i] = new HashFunction(DEFAULT_SIZE, seeds[i]); } } public void add(String value) { for (HashFunction function : functions) { bitSet.set(function.toHash(value)); } } public boolean contains(String value) { for (HashFunction function : functions) { // 只要有一个不存在,则 value 一定不存在 boolean result = bitSet.get(function.toHash(value)); if (Objects.equals(result, false)) { return false; } } return true; } public static void main(String[] args) { TestBloomFilter bloomFilter = new TestBloomFilter(); bloomFilter.add("斗罗大陆"); bloomFilter.add("辰东"); System.out.println(bloomFilter.contains("我爱吃西红柿")); // false System.out.println(bloomFilter.contains("辰东")); // true } /** * 作用就是算 hash值 * 静态类,便于处理 * @author ZZ_C * */ static class HashFunction { private int size; private int seed; public HashFunction(int size, int seed) { super(); this.size = size; this.seed = seed; } public int toHash(String value) { int h; return (value == null) ? 0 : Math.abs(seed * (size - 1) & ((h = value.hashCode()) ^ (h >>> 16))); } } }

应用场景

Bloom Filter 在使用场景上分为两种,一种是单体架构,一个是分布式架构。
单体架构:Gava,redis
分布式架构: redis bloom(需要自行安装到 redis 中)

缓存击穿

使用布隆过滤器,将全部的有效数据都走一遍布隆过滤器,这样新来请求时,先走一遍请求的元素是否能通过布隆过滤器的验证,若未通过就直接放弃请求,若通过再执行查询

去重

用户浏览记录存入数据库时,会在Filter上通过key的hash算法存储判断其是否存在,类似于数据存在数据库中,判断该数据是否存在的信息即元数据存放在BloomFilter中,避免了每次判断数据是否存在都要去数据库exist一遍;这样推送新闻时通过布隆过滤器判断,推送内容是否已经存在,如果存在则不推送,如果不存在则推送;


__EOF__

本文作者之士咖啡
本文链接https://www.cnblogs.com/zz-1q/p/16263667.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   之士咖啡  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示