Redis-避免缓存穿透的利器之BloomFilter

目录

  • Redis-避免缓存穿透的利器之BloomFilter
    • Bloom Filter 概念
    • Bloom Filter 原理
      • 缓存穿透
    • Bloom Filter的缺点
    • 常见问题
    • go语言实现

你在开发或者面试过程中,有没有遇到过 海量数据需要查重,缓存穿透怎么避免等等这样的问题呢?下面这个东西超屌,好好了解下,面试过关斩将,凸显你的不一样。

Bloom Filter 概念

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

Bloom Filter 原理

布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。

Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率

缓存穿透

每次查询都会直接打到DB

简而言之,言而简之就是我们先把我们数据库的数据都加载到我们的过滤器中,比如数据库的id现在有:1、2、3

那就用id:1 为例子他在上图中经过三次hash之后,把三次原本值0的地方改为1

下次数据进来查询的时候如果id的值是1,那么我就把1拿去三次hash 发现三次hash的值,跟上面的三个位置完全一样,那就能证明过滤器中有1的

反之如果不一样就说明不存在了

那应用的场景在哪里呢?一般我们都会用来防止缓存击穿

简单来说就是你数据库的id都是1开始然后自增的,那我知道你接口是通过id查询的,我就拿负数去查询,这个时候,会发现缓存里面没这个数据,我又去数据库查也没有,一个请求这样,100个,1000个,10000个呢?你的DB基本上就扛不住了,如果在缓存里面加上这个,是不是就不存在了,你判断没这个数据就不去查了,直接return一个数据为空不就好了嘛。

这玩意这么好使那有啥缺点么?有的,我们接着往下看

Bloom Filter的缺点

bloom filter之所以能做到在时间和空间上的效率比较高,是因为牺牲了判断的准确率、删除的便利性

存在误判,可能要查到的元素并没有在容器中,但是hash之后得到的k个位置上值都是1。如果bloom filter中存储的是黑名单,那么可以通过建立一个白名单来存储可能会误判的元素。

删除困难。一个放入容器的元素映射到bit数组的k个位置上是1,删除的时候不能简单的直接置为0,可能会影响其他元素的判断。可以采用Counting Bloom Filter

常见问题

1、为何要使用多个哈希函数?

Hash本身就会面临冲突,如果只使用一个哈希函数,那么冲突的概率会比较高。例如长度100的数组,如果只使用一个哈希函数,添加一个元素后,添加第二个元素时冲突的概率为1%,添加第三个元素时冲突的概率为2%…但如果使用两个哈希函数,添加一个元素后,添加第二个元素时冲突的概率降为万分之4(四种可能的冲突情况,情况总数100x100)

go语言实现

package mainimport ("fmt""github.com/bits-and-blooms/bitset"
)//设置哈希数组默认大小为16
const DefaultSize = 16//设置种子,保证不同哈希函数有不同的计算方式
var seeds = []uint{7, 11, 13, 31, 37, 61}//布隆过滤器结构,包括二进制数组和多个哈希函数
type BloomFilter struct {//使用第三方库set *bitset.BitSet//指定长度为6hashFuncs [6]func(seed uint, value string) uint
}//构造一个布隆过滤器,包括数组和哈希函数的初始化
func NewBloomFilter() *BloomFilter {bf := new(BloomFilter)bf.set = bitset.New(DefaultSize)for i := 0; i < len(bf.hashFuncs); i++ {bf.hashFuncs[i] = createHash()}return bf
}//构造6个哈希函数,每个哈希函数有参数seed保证计算方式的不同
func createHash() func(seed uint, value string) uint {return func(seed uint, value string) uint {var result uint = 0for i := 0; i < len(value); i++ {result = result*seed + uint(value[i])}//length = 2^n 时,X % length = X & (length - 1)return result & (DefaultSize - 1)}
}//添加元素
func (b *BloomFilter) add(value string) {for i, f := range b.hashFuncs {//将哈希函数计算结果对应的数组位置1b.set.Set(f(seeds[i], value))}
}//判断元素是否存在
func (b *BloomFilter) contains(value string) bool {//调用每个哈希函数,并且判断数组对应位是否为1//如果不为1,直接返回false,表明一定不存在for i, f := range b.hashFuncs {//result = result && b.set.Test(f(seeds[i], value))if !b.set.Test(f(seeds[i], value)) {return false}}return true
}func main() {filter := NewBloomFilter()filter.add("asd")fmt.Println(filter.contains("asd"))fmt.Println(filter.contains("2222"))fmt.Println(filter.contains("155343"))
}

输出结果如下:

true
false
false

Redis之布隆过滤器(BloomFilter)相关推荐

  1. 布隆过滤器 - Redis 布隆过滤器,Guava 布隆过滤器 BloomFilter

    文章目录 布隆过滤器 - Redis 布隆过滤器,Guava 布隆过滤器 BloomFilter 1.布隆过滤器的起源,用途 2.布隆过滤器的概念 3.布隆过滤器的优缺点 1.优点 2.缺点 4.应用 ...

  2. Flink 结合 布隆过滤器(BloomFilter) 实现去重

    本文开头附:Flink 学习路线系列 ^ _ ^ 1.实时系统去重方案 使用Redis,将实时系统每条数据都去和 Redis 进行判断: 使用 HashSet,因为 HashSet 本身就是无序不重复 ...

  3. 04 布隆过滤器BloomFilter

    是什么 布隆过滤器(英语:Bloom Filter)是 1970 年由布隆提出的. 它实际上是一个很长的二进制数组+一系列随机hash算法映射函数,主要用于判断一个元素是否在集合中. 通常我们会遇到很 ...

  4. 布隆过滤器 布谷鸟过滤器 Redis 安装布隆过滤器

    布隆过滤器 &布谷鸟过滤器 & Redis 安装布隆过滤器 1.布隆过滤器 1.1 简介 百度百科:布隆过滤器(Bloom Filter)是1970年由布隆提出的.它实际上是一个很长的 ...

  5. 布隆过滤器(BloomFilter)原理 实现和性能测试

    目录 BloomFilter的原理 如何确定最优的m和k? guava中的BloomFilter 使用案例 和HashSet对比 测试环境 测试方式 BloomFilter vs HashSet 在不 ...

  6. Redis 高级主题之布隆过滤器(BloomFilter)

    最近计划准备整理几篇关于Reids高级主题的博文,本文整理的是关于布隆过滤器在Redis中如何应用,先来一张思维导图浏览全文. 1. 认识BloomFilter 1.1 原理 布隆过滤器,英文叫Blo ...

  7. 【redis】详解布隆过滤器BloomFilter的原理,使用场景和注意事项

    文章目录 1. 什么是布隆过滤器 2. 实现原理 2.1 HashMap 的问题 2.2 布隆过滤器数据结构 2.3 BloomFilter 的缺点 2.4 如何选择哈希函数个数和布隆过滤器长度 3. ...

  8. Redis进阶-布隆过滤器

    文章目录 Pre 布隆能解决哪些问题? BloomFilter实现原理 构建布隆过滤器 构建布隆的误差率 实际误差率推算 布隆过滤器 (JVM级别) 布隆过滤器 (分布式) Bloom Filter的 ...

  9. Redis中布隆过滤器的使用及原理

    <玩转Redis>系列文章主要讲述Redis的基础及中高级应用.本文是<玩转Redis>系列第[11]篇,最新系列文章请前往公众号"zxiaofan"查看, ...

最新文章

  1. 揭秘:一个月不摸鱼能写多少代码?
  2. js 移动端 滑块验证码插件_VUE技术详解,Vue.js从入门到精通
  3. pps+linux版+x64,64位Ubuntu 11.04安装PPS的办法
  4. selenium,webdriver 执行js语句 对象是百度
  5. 思科怎么隐藏端口_这些著名商标下的隐藏设计,你能发现吗?
  6. GIS专业核心课程电子教材配套实验数据汇总(持续更新)
  7. VS Code 中的文件添加图标的插件vscode-icons
  8. static静态关键词 1214
  9. c++类成员变量初始化详解
  10. C# Console Application
  11. 如何把电脑加上公司的域
  12. 1125: 上三角矩阵的判断
  13. JavaScript判断鼠标中键滑轮的上下滚动
  14. 关于 ‘cosylocal‘ 进程占满内存的问题
  15. html页面高度和宽度,html和body元素的高度和宽度
  16. 安卓MediaPlayer源码跟读解析
  17. win10安装docker及docker安装镜像
  18. AMESim与Matlab/Simulink联合仿真步骤(最新软件版本!)
  19. 14、DHCP(自动分配IP地址)
  20. 第六课 511遇见易语言大漠找字FindStrFastEx打多怪实例

热门文章

  1. 海量数据相似数据查找方法(ANN):【高维稀疏向量的相似查找——MinHash, LSH, SimHash】【稠密向量的相似查找——Faiss、Annoy、ScaNN、Hnswlib】
  2. grep 同时查找多个文件
  3. 解决CPLEX安装后无法运行代码,报错乱码(错误显示:ÔËÐÐÅäÖá°配置 1¡±²»´æÔڡ£)
  4. Redis下载安装配置(linux版本)
  5. SQL实现排序,并输出序号
  6. 基本数据类型 java
  7. 相关算法---贪心算法
  8. 这几道tomcat面试题,最后两道难倒我了
  9. 框架分析--框架驱动
  10. [C++]打开新世界的大门之C++入门