布隆过滤器

  • 布隆过滤器(Bloom Filter)是一种非常巧妙的数据结构,用来判断一个元素是否在一个集合中。它的特点是空间效率极高,但也有一定的误判率。我们来一步步拆解讲清楚它的原理、特点和应用

一句话总结:布隆过滤器是一个基于位数组和多个哈希函数的概率型数据结构,它能快速判断一个元素是否不在集合中,但不能保证判断元素在集合中一定准确(可能会误判)。

布隆过滤器的结构

布隆过滤器主要包含两个核心组成:

  1. 位数组(Bit Array):长度为 m,初始化时每一位都是 0。
  2. k 个哈希函数(Hash Functions):每个哈希函数将输入元素映射到 [0, m-1] 范围内的一个整数。

插入元素的过程(add)

举个例子,把字符串 “apple” 加入布隆过滤器:

  1. 用 k 个哈希函数分别计算 “apple” 的 k 个位置,比如是 [5, 12, 29]。
  2. 把这几个位置的位(bit)都设置为 1。

即:bit[5] = 1, bit[12] = 1, bit[29] = 1

查询元素的过程(contains / mightContain)

以 “apple” 为例,想判断它是否在集合中:

  1. 用同样的 k 个哈希函数计算出它对应的 k 个位置。
  2. 如果这些位置中有任意一个是 0,那说明 “apple” 一定不在。
  3. 如果这些位置都是 1,可能在(但不保证一定在,可能是别的元素碰巧把这些位置都设置成了 1)。

布隆过滤器的特点

特性说明
查询速度快哈希+位数组,时间复杂度为 O(k)
空间效率高相比普通集合结构(如哈希表),占用内存非常少
存在误判有可能会误判元素在集合中(假阳性),但不会漏报(不会错过实际存在的元素)
不可删除元素标准布隆过滤器无法删除元素(否则可能影响其他元素)

布隆过滤器的应用场景

  1. 缓存穿透拦截(比如 Redis 缓存系统中先判断 key 是否可能存在)
  2. 黑名单系统(快速判断用户/IP 是否命中黑名单)
  3. 爬虫去重(URL 去重)
  4. 数据库/搜索引擎中判断关键词是否存在于某个倒排索引中
  5. 区块链、分布式系统中的去重、同步校验等场景

golang 代码

package main

import (
    "fmt"
    "hash/fnv"
)

// BloomFilter 结构体
type BloomFilter struct {
    bitset     []bool
    size       uint
    hashFuncs  []func(string) uint
}

// 创建新的布隆过滤器
func NewBloomFilter(size uint, hashCount int) *BloomFilter {
    bf := &BloomFilter{
        bitset:    make([]bool, size),
        size:      size,
        hashFuncs: make([]func(string) uint, hashCount),
    }

    // 初始化多个哈希函数(使用不同的种子)
    for i := 0; i < hashCount; i++ {
        seed := uint32(i + 1)
        bf.hashFuncs[i] = func(data string) uint {
            h := fnv.New32a()
            h.Write([]byte(fmt.Sprintf("%d%s", seed, data))) // 模拟不同种子
            return uint(h.Sum32()) % size
        }
    }

    return bf
}

// 添加元素
func (bf *BloomFilter) Add(item string) {
    for _, hashFunc := range bf.hashFuncs {
        index := hashFunc(item)
        bf.bitset[index] = true
    }
}

// 检查元素是否可能存在
func (bf *BloomFilter) MightContain(item string) bool {
    for _, hashFunc := range bf.hashFuncs {
        index := hashFunc(item)
        if !bf.bitset[index] {
            return false
        }
    }
    return true
}

// 示例用法
func main() {
    bf := NewBloomFilter(1000, 3)

    bf.Add("apple")
    bf.Add("banana")

    fmt.Println("Contains apple:", bf.MightContain("apple"))     // true
    fmt.Println("Contains banana:", bf.MightContain("banana"))   // true
    fmt.Println("Contains orange:", bf.MightContain("orange"))   // false(大概率)
}

代码说明

  • bitset 是一个布尔数组,用来存储位信息。
  • 使用 fnv.New32a() 哈希函数,模拟多个哈希函数是通过加不同前缀种子来实现的。
  • Add() 方法将多个哈希索引位置设置为 true。
  • MightContain() 检查对应的所有位是否都为 true,否则就说明元素一定不在集合中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值