victoriaMetrics库布隆过滤器初始化及使用详解
IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《victoriaMetrics库布隆过滤器初始化及使用详解》,聊聊初始化、victoriaMetrics布隆过滤器,我们一起来看看吧!
代码路径:/lib/bloomfilter
概述
victoriaMetrics的vmstorage
组件会接收上游传递过来的指标,在现实场景中,指标或瞬时指标的数量级可能会非常恐怖,如果不限制缓存的大小,有可能会由于cache miss而导致出现过高的slow insert。
为此,vmstorage提供了两个参数:maxHourlySeries
和maxDailySeries
,用于限制每小时/每天添加到缓存的唯一序列。
唯一序列指表示唯一的时间序列,如metrics{label1="value1",label2="value2"}属于一个时间序列,但多条不同值的metrics{label1="value1",label2="value2"}属于同一条时间序列。victoriaMetrics使用如下方式来获取时序的唯一标识:
func getLabelsHash(labels []prompbmarshal.Label) uint64 { bb := labelsHashBufPool.Get() b := bb.B[:0] for _, label := range labels { b = append(b, label.Name...) b = append(b, label.Value...) } h := xxhash.Sum64(b) bb.B = b labelsHashBufPool.Put(bb) return h }
限速器的初始化
victoriaMetrics使用了一个类似限速器的概念,限制每小时/每天新增的唯一序列,但与普通的限速器不同的是,它需要在序列级别进行限制,即判断某个序列是否是新的唯一序列,如果是,则需要进一步判断一段时间内缓存中新的时序数目是否超过限制,而不是简单地在请求层面进行限制。
hourlySeriesLimiter = bloomfilter.NewLimiter(*maxHourlySeries, time.Hour) dailySeriesLimiter = bloomfilter.NewLimiter(*maxDailySeries, 24*time.Hour)
下面是新建限速器的函数,传入一个最大(序列)值,以及一个刷新时间。该函数中会:
- 初始化一个限速器,限速器的最大元素个数为
maxItems
- 则启用了一个goroutine,当时间达到
refreshInterval
时会重置限速器
func NewLimiter(maxItems int, refreshInterval time.Duration) *Limiter { l := &Limiter{ maxItems: maxItems, stopCh: make(chan struct{}), } l.v.Store(newLimiter(maxItems)) //1 l.wg.Add(1) go func() { defer l.wg.Done() t := time.NewTicker(refreshInterval) defer t.Stop() for { select { case <p>限速器只有一个核心函数<code>Add</code>,当vmstorage接收到一个指标之后,会(通过<code>getLabelsHash</code>计算该指标的唯一标识(h),然后调用下面的<code>Add</code>函数来判断该唯一标识是否存在于缓存中。</p> <p>如果当前存储的元素个数大于等于允许的最大元素,则通过过滤器判断缓存中是否已经存在该元素;否则将该元素直接加入过滤器中,后续允许将该元素加入到缓存中。</p> <pre class="brush:groovy;">func (l *Limiter) Add(h uint64) bool { lm := l.v.Load().(*limiter) return lm.Add(h) } func (l *limiter) Add(h uint64) bool { currentItems := atomic.LoadUint64(&l.currentItems) if currentItems >= uint64(l.f.maxItems) { return l.f.Has(h) } if l.f.Add(h) { atomic.AddUint64(&l.currentItems, 1) } return true }
上面的过滤器采用的是布隆过滤器,核心函数为Has
和Add
,分别用于判断某个元素是否存在于过滤器中,以及将元素添加到布隆过滤器中。
过滤器的初始化函数如下,bitsPerItem
是个常量,值为16。bitsCount
统计了过滤器中的总bit数,每个bit表示某个值的存在性。bits
以64bit为单位的(后续称之为slot,目的是为了在bitsCount中快速检索目标bit)。计算bits
时加上63
的原因是为了四舍五入向上取值,比如当maxItems=1时至少需要1个unit64的slot。
func newFilter(maxItems int) *filter { bitsCount := maxItems * bitsPerItem bits := make([]uint64, (bitsCount+63)/64) return &filter{ maxItems: maxItems, bits: bits, } }
为什么bitsPerItem
为16?这篇文章给出了如何计算布隆过滤器的大小。在本代码中,k为4(hashesCount
),期望的漏失率为0.003(可以从官方的filter_test.go
中看出),则要求总存储和总元素的比例为15,为了方便检索slot(64bit,为16的倍数),将之设置为16。
if p > 0.003 { t.Fatalf("too big false hits share for maxItems=%d: %.5f, falseHits: %d", maxItems, p, falseHits) }
下面是过滤器的Add
操作,目的是在过滤器中添加某个元素。Add
函数中没有使用多个哈希函数来计算元素的哈希值,转而改变同一个元素的值,然后对相应的值应用相同的哈希函数,元素改变的次数受hashesCount
的限制。
- 获取过滤器的完整存储,并转换为以bit单位
- 将元素
h
转换为byte数组,便于xxhash.Sum64计算 - 后续将执行hashesCount次哈希,降低漏失率
- 计算元素h的哈希
- 递增元素
h
,为下一次哈希做准备 - 取余法获取元素的bit范围
- 获取元素所在的slot(即uint64大小的bit范围)
- 获取元素所在的slot中的bit位,该位为1表示该元素存在,为0表示该元素不存在
- 获取元素所在bit位的掩码
- 加载元素所在的slot的数值
- 如果
w & mask
结果为0,说明该元素不存在, - 将元素所在的slot(
w
)中的元素所在的bit位(mask)置为1,表示添加了该元素 - 由于
Add
函数可以并发访问,因此bits[i]
有可能被其他操作修改,因此需要通过重新加载(14)并通过循环来在bits[i]
中设置该元素的存在性
func (f *filter) Add(h uint64) bool { bits := f.bits maxBits := uint64(len(bits)) * 64 //1 bp := (*[8]byte)(unsafe.Pointer(&h))//2 b := bp[:] isNew := false for i := 0; i <p>看懂了<code>Add</code>函数,<code>Has</code>就相当简单了,它只是<code>Add</code>函数的缩减版,无需设置<code>bits[i]</code>:</p> <pre class="brush:groovy;">func (f *filter) Has(h uint64) bool { bits := f.bits maxBits := uint64(len(bits)) * 64 bp := (*[8]byte)(unsafe.Pointer(&h)) b := bp[:] for i := 0; i <h2>总结</h2> <p>由于victoriaMetrics的过滤器采用的是布隆过滤器,因此它的限速并不精准,在源码条件下, 大约有3%的偏差。但同样地,由于采用了布隆过滤器,降低了所需的内存以及相关计算资源。此外victoriaMetrics的过滤器实现了并发访问。</p> <p>在大流量场景中,如果需要对请求进行相对精准的过滤,可以考虑使用布隆过滤器,降低所需要的资源,但前提是过滤的结果能够忍受一定程度的漏失率。</p> <p>今天关于《victoriaMetrics库布隆过滤器初始化及使用详解》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!</p>

- 上一篇
- golang中sync.Mutex的实现方法

- 下一篇
- 如何解决goland,idea全局搜索快捷键失效问题
-
- 虚心的钢笔
- 这篇文章真是及时雨啊,好细啊,真优秀,已收藏,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-05-12 17:28:59
-
- 怕孤独的河马
- 细节满满,已加入收藏夹了,感谢老哥的这篇博文,我会继续支持!
- 2023-05-03 22:54:56
-
- 活力的小懒猪
- 赞 👍👍,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢师傅分享技术贴!
- 2023-03-16 08:44:28
-
- 雪白的发卡
- 感谢大佬分享,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢师傅分享技术贴!
- 2023-02-14 06:06:39
-
- 合适的春天
- 这篇技术贴真及时,太全面了,感谢大佬分享,收藏了,关注作者大大了!希望作者大大能多写Golang相关的文章。
- 2023-01-25 16:45:28
-
- 平常的大神
- 好细啊,已加入收藏夹了,感谢作者的这篇博文,我会继续支持!
- 2023-01-20 14:49:17
-
- 典雅的镜子
- 赞 👍👍,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢作者大大分享技术文章!
- 2023-01-16 10:28:52
-
- 合适的果汁
- 这篇技术贴真是及时雨啊,太详细了,很有用,已加入收藏夹了,关注up主了!希望up主能多写Golang相关的文章。
- 2023-01-16 09:28:56
-
- 闪闪的飞机
- 太细致了,收藏了,感谢大佬的这篇文章内容,我会继续支持!
- 2023-01-05 00:14:22
-
- Golang · Go教程 | 1天前 |
- TigervncDebian多用户共享桌面超简单教程
- 482浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Go语言新手必看!切片vs数组,一次搞定这两个核心知识点
- 472浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Docker在Debian上运行超简单教程(保姆级教学)
- 210浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Debian设置hostname踩坑记录:权限问题大揭秘
- 334浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Debian装SQLServer?这些问题你一定要注意!
- 284浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Debian系统下Jenkins自动化部署脚本教学
- 367浏览 收藏
-
- Golang · Go教程 | 2天前 |
- DebianSwap服务器应用实测,这些场景真的用得上!
- 319浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Debian跑TigerVNC实测!真香警告,快来看看性能咋样~
- 171浏览 收藏
-
- Golang · Go教程 | 2天前 |
- 在Debian上玩转SQLServer备份还原,手把手教你一步步操作
- 498浏览 收藏
-
- Golang · Go教程 | 2天前 |
- DebianOverlay不会玩?手把手教你轻松定制化安装
- 258浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Go语言实战:time.Ticker&time.After用法区别及避坑技巧
- 240浏览 收藏
-
- Golang · Go教程 | 2天前 |
- Debian系统如何快速定位&干掉那些讨厌的僵尸进程
- 317浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 21次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 50次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 58次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 53次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 60次使用
-
- k8s在go语言中的使用及client 初始化简介
- 2023-01-07 118浏览
-
- goGin安装及初始化操作示例
- 2023-01-01 159浏览
-
- go语言数组及结构体继承和初始化示例解析
- 2023-02-16 320浏览
-
- Go语言基础变量的声明及初始化示例详解
- 2023-02-25 415浏览
-
- Golang 空map和未初始化map的注意事项说明
- 2022-12-28 102浏览