前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >go 布隆过滤器_布隆过滤器 redis

go 布隆过滤器_布隆过滤器 redis

作者头像
全栈程序员站长
发布于 2022-11-08 07:00:57
发布于 2022-11-08 07:00:57
66600
代码可运行
举报
运行总次数:0
代码可运行

最近面临这样的场景: 2亿+数据需要调用后端服务A,业务需要1min处理完成,那么A服务承载的tps达到惊人的300w……必须想办法降低tps。 那么方案来了:1、把时间窗口拉长 2、降低待处理数据量。 拉长时间业务肯定是接受不了的,但是按照以往的经验,这部分数据并不全部需要处理,可能仅有一半真正需要调用A服务,所以我们可以把1亿数据给过滤掉。 这里我们维护一个布隆过滤器来进行数据的过滤。

1. 布隆过滤器的概念(百科)

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

2. 布隆过滤器应用场景

deny list

数据判重

预过滤

3. 原理

核心是一个长度为m的bit array和k个hash方法。

如下图,我们将一个newsid通过3个hash方法映射到长为8的数组上。

判断newsid是否存在,则看数组中3个位置是否都取到1:全为1,newsid可能存在于集合中;不全为1,newsid一定不存在于集合中。

4. 特性

容易发现,布隆过滤器存在假阳性的情况,即将不在集合中的元素误判为在集合中。过滤器中的元素个数越多,假阳性的可能性越大。

同时,元素可以被加入过滤器,但很难从过滤器中删除(有可能删除的当前元素与其他元素共享了某一个bit,造成假阴性)。

根据假阳性率计算公式:

可知在哈希函数的个数k一定的情况下:

  • 位数组长度m越大,假阳性率越低;
  • 已插入元素的个数n越大,假阳性率越高。

5. 上代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// CalBloomSize 计算布隆过滤器位图大小
// elemNum 元素个数
// errorRate 误判率
func CalBloomSize(elemNum uint64, errRate float64) uint64 {
   var bloomBitsSize = float64(elemNum) * math.Log(errRate) / (math.Log(2) * math.Log(2)) * (-1)
   return uint64(math.Ceil(bloomBitsSize))
}

// CalHashFuncNum 计算需要的哈希函数数量
// elemNum 元素个数
// bloomSize 布隆过滤器位图大小
func CalHashFuncNum(elemNum, bloomSize uint64) uint64 {
   var k = math.Log(2) * float64(bloomSize) / float64(elemNum)
   return uint64(math.Ceil(k))
}

// Filter
type Filter struct {
   ElemNum     uint64
   BloomSize   uint64 
   HashFuncNum uint64
   ErrRate     float64

   bitMap *bitset.BitSet
   keys   map[uint32]bool
}

// NewFilter NewFilter
func NewFilter(elemNum, bloomSize, hashFuncNum uint64, errRate float64) *Filter {
   return &Filter{ElemNum: elemNum, BloomSize: bloomSize, HashFuncNum: hashFuncNum, ErrRate: errRate}
}

// Init 初始化布隆过滤器
func (f *Filter) Init() {
   // 分配布隆过滤器位图
   f.bitMap = bitset.New(uint(f.BloomSize))
   // 初始化哈希函数
   // 是否是类似HMAC-SHA256那种通过改变passphase值形成不同的哈希函数
   f.keys = make(map[uint32]bool)
   for uint64(len(f.keys)) < f.HashFuncNum {
      randNum, err := rand.Int(rand.Reader, new(big.Int).SetUint64(math.MaxUint32))
      if err != nil {
         panic(err)
      }
      f.keys[uint32(randNum.Uint64())] = true
   }
}

// Add  Add
func (f *Filter) Add(elem []byte) {
   var buf [4]byte
   for k := range f.keys {
      binary.LittleEndian.PutUint32(buf[:], k)
      hashResult := new(big.Int).SetBytes(HMACWithSHA128(elem, buf[:]))
      result := hashResult.Mod(hashResult, big.NewInt(int64(f.BloomSize)))
      // 把result对应的bit置1
      f.bitMap.Set(uint(result.Uint64()))
   }
}

// IsContain 判断元素是否在集合里面
func (f *Filter) IsContain(elem []byte) bool {
   var buf [4]byte
   for k := range f.keys {
      binary.LittleEndian.PutUint32(buf[:], k)
      hashResult := new(big.Int).SetBytes(HMACWithSHA128(elem, buf[:]))
      result := hashResult.Mod(hashResult, big.NewInt(int64(f.BloomSize)))
      // 查询result对应的bit是否被置1
      if !f.bitMap.Test(uint(result.Uint64())) {
         return false
      }
   }
   return true
}

// HMACWithSHA128 通过加盐生成不同的hash值
func HMACWithSHA128(seed []byte, key []byte) []byte {
   hmac512 := hmac.New(sha1.New, key)
   hmac512.Write(seed)
   return hmac512.Sum(nil)
}

测试:2亿长16B的元素,失误率0.0001,分配到过滤器需要0.4G,如果放hash表,则需要3.2G

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/185284.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月6日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
详解布隆过滤器的原理和实现
针对以上问题常规做法是:查询数据库,数据库硬扛,如果压力并不大可以使用此方法,保持简单即可。
玖柒的小窝
2021/12/07
9220
详解布隆过滤器的原理和实现
大白话布隆过滤器
近期在做推荐系统中已读内容去重的相关内容,刚好用到了布隆过滤器,于是写了一篇文章记录分享一下。
Bug开发工程师
2020/04/24
1.7K0
大白话布隆过滤器
victoriaMetrics库之布隆过滤器
victoriaMetrics的vmstorage组件会接收上游传递过来的指标,在现实场景中,指标或瞬时指标的数量级可能会非常恐怖,如果不限制缓存的大小,有可能会由于cache miss而导致出现过高的slow insert。
charlieroro
2022/05/09
4991
victoriaMetrics库之布隆过滤器
Redis实现布隆过滤器解析
    1)布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
忧愁的chafry
2022/10/30
1.4K0
Redis实现布隆过滤器解析
Go语言实现布谷鸟过滤器
在我们工作中,如果遇到如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断一般想到的是将集合中所有元素保存起来,然后通过比较确定。如果通过性能最好的Hash表来进行判断,那么随着集合中元素的增加,我们需要的存储空间也会呈现线性增长,最终达到瓶颈。
luozhiyun
2021/02/28
1.3K0
巧用布隆过滤器提取数据摘要
在telemetry采集中,由于数据量极大,一般采用分布式架构;使用消息队列来进行各系统的解耦。有系统如下:
超级大猪
2022/11/29
4340
巧用布隆过滤器提取数据摘要
什么是布隆过滤器,隆过滤器是干什么用的?
大家看下这幅图,用户可能进行了一次条件错误的查询,这时候 redis 是不存在的,按照常规流程就是去数据库找了,可是这是一次错误的条件查询,数据库当然也不会存在,也不会往 redis 里面写值,返回给用户一个空,这样的操作一次两次还好,可是次数多了还了得,我放 redis 本来就是为了挡一挡,减轻数据库的压力,现在 redis 变成了形同虚设,每次还是去数据库查找了,这个就叫做缓存穿透,相当于 redis 不存在了,被击穿了,对于这种情况很好解决,我们可以在 redis 缓存一个空字符串或者特殊字符串,比如 &&,下次我们去 redis 中查询的时候,当取到的值是空或者 &&,我们就知道这个值在数据库中是没有的,就不会在去数据库中查询。
用户2242639
2021/06/29
6290
布隆过滤器:原理与应用
这个时候,布隆过滤器(Bloom Filter)就派上了用场。 作为一种空间高效的概率型数据结构,布隆过滤器能够快速有效地检测一个元素是否属于一个集合。其应用广泛,从网络爬虫的网页去重,到数据库查询优化,乃至比特币网络的交易匹配,都离不开它的身影。
BookSea
2023/10/12
5060
Redis集群实现布隆过滤器
封面为好友拍摄的照片,想查看更多微信公众号搜索:JavaBoy王皓或csdn博客搜索:TenaciousD
胖虎
2019/06/26
1.7K0
Redis集群实现布隆过滤器
布隆过滤器 原理及优缺点分析_布隆过滤器误判怎么办
百度百科解释他可以判断一个元素是否在集合中,后面还说了他的效率呀什么的都很好,那既然如此,我们再想象一下为什么需要它!
全栈程序员站长
2022/11/08
7750
布隆过滤器 原理及优缺点分析_布隆过滤器误判怎么办
手写redis布隆过滤器,你真的会吗?
redis作为现在主流的nosql数据库,备受瞩目;它的丰富的value类型,以及它的偏向计算向数据移动属性减少IO的成本问题。备受开发人员的青睐。通常我们使用redis作为数据缓存来使用,但是作为缓存redis会有一些问题,就是缓存穿透问题、击穿、雪崩、一致性双写。本次主要讲解的就是穿透问题
@派大星
2023/06/28
2430
手写redis布隆过滤器,你真的会吗?
详解布隆过滤器原理,及分布式运用方法_布隆过滤器最小误差
布隆过滤器是一个叫“布隆”的人提出的,本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure)。它本身是一个很长的二进制向量,特点是高效地插入和查询,可以用来确定 “某一条数据一定不存在或者可能存在一个集合中”。
全栈程序员站长
2022/11/08
1.4K0
详解布隆过滤器原理,及分布式运用方法_布隆过滤器最小误差
布隆过滤器(Bloom Filter):如何在海量数据中轻松找到你要的答案?
无论是红黑树、平衡二叉树、散列表,结点都是存储的key-value对。而有些场景,内存是有限的,仅需要了解key是否存在,不想知道具体内容(value)。
Lion 莱恩呀
2024/10/09
3510
布隆过滤器(Bloom Filter):如何在海量数据中轻松找到你要的答案?
品味布隆过滤器 Bloom filter的设计之美
你可能没想到: RocketMQ、 Hbase 、Cassandra 、LevelDB 、RocksDB 这些知名项目中都有布隆过滤器的身影。
勇哥java实战
2023/04/14
2.4K0
品味布隆过滤器 Bloom filter的设计之美
布隆过滤器解读(Java实现)
布隆过滤器:(布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。
一个风轻云淡
2023/12/13
5240
基于Redis扩展模块的布隆过滤器使用
什么是布隆过滤器? 它实际上是一个很长的二进制向量和一系列随机映射函数。把一个目标元素通过多个hash函数的计算,将多个随机计算出的结果映射到二进制向量的位中,依次来间接标记一个元素是否存在于一个集合中。 布隆过滤器可以做什么? 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 布隆过滤器特点 如果布隆过滤器显示一个元素不存在于集合中,那么这个元素100%不存在与集合当中 如果布隆过滤器显示一个元素存在于集合中,那么很有可能存在,可能性取决于对布隆过滤器的定义(BF.RESERVE {key} {error_rate} {capacity})
星哥玩云
2022/08/18
6170
基于Redis扩展模块的布隆过滤器使用
BloomFilter怎么用?使用布隆过滤器来判断key是否存在?「建议收藏」
今天跟一个同事聊了一个问题,说最近在做推荐,如何判断用户是否看过这个片段呢?想了一下,正好可以使用布隆过滤器来完成这个需求。
全栈程序员站长
2022/11/16
1.3K0
BloomFilter怎么用?使用布隆过滤器来判断key是否存在?「建议收藏」
Redis(5)——亿级数据过滤和布隆过滤器
上一次 我们学会了使用 HyperLogLog 来对大数据进行一个估算,它非常有价值,可以解决很多精确度不高的统计需求。但是如果我们想知道某一个值是不是已经在 HyperLogLog 结构里面了,它就无能为力了,它只提供了 pfadd 和 pfcount 方法,没有提供类似于 contains 的这种方法。
我没有三颗心脏
2020/03/20
1.4K0
Redis(5)——亿级数据过滤和布隆过滤器
高并发系统一定要考虑的 Bloom Filter 布隆过滤器
一般我们用来判断一个元素是否存在,会想到用 List,Map,Set 等,会将元素先保存下来,然后进行筛选。
用户1577699
2020/04/29
1K0
布隆过滤器Bloom Filter简介
当需要判断一个元素是否存在于海量数据集合中,不仅查找时间慢,还会占用大量存储空间,接下来看一下布隆过滤器如何解决这个问题
全栈程序员站长
2022/06/29
5070
布隆过滤器Bloom Filter简介
相关推荐
详解布隆过滤器的原理和实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验