<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
程式碼路徑:/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
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 <-t.C: l.v.Store(newLimiter(maxItems))//2 case <-l.stopCh: return } } }() return l }
限速器只有一個核心函數Add
,當vmstorage接收到一個指標之後,會(通過getLabelsHash
計算該指標的唯一標識(h),然後呼叫下面的Add
函數來判斷該唯一標識是否存在於快取中。
如果當前儲存的元素個數大於等於允許的最大元素,則通過過濾器判斷快取中是否已經存在該元素;否則將該元素直接加入過濾器中,後續允許將該元素加入到快取中。
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
的限制。
h
轉換為byte陣列,便於xxhash.Sum64計算h
,為下一次雜湊做準備w & mask
結果為0,說明該元素不存在,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 < hashesCount; i++ {//3 hi := xxhash.Sum64(b)//4 h++ //5 idx := hi % maxBits //6 i := idx / 64 //7 j := idx % 64 //8 mask := uint64(1) << j //9 w := atomic.LoadUint64(&bits[i])//10 for (w & mask) == 0 {//11 wNew := w | mask //12 if atomic.CompareAndSwapUint64(&bits[i], w, wNew) {//13 isNew = true//14 break } w = atomic.LoadUint64(&bits[i])//14 } } return isNew }
看懂了Add
函數,Has
就相當簡單了,它只是Add
函數的縮減版,無需設定bits[i]
:
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 < hashesCount; i++ { hi := xxhash.Sum64(b) h++ idx := hi % maxBits i := idx / 64 j := idx % 64 mask := uint64(1) << j w := atomic.LoadUint64(&bits[i]) if (w & mask) == 0 { return false } } return true }
由於victoriaMetrics的過濾器採用的是布隆過濾器,因此它的限速並不精準,在原始碼條件下, 大約有3%的偏差。但同樣地,由於採用了布隆過濾器,降低了所需的記憶體以及相關計算資源。此外victoriaMetrics的過濾器實現了並行存取。
在大流量場景中,如果需要對請求進行相對精準的過濾,可以考慮使用布隆過濾器,降低所需要的資源,但前提是過濾的結果能夠忍受一定程度的漏失率。
以上就是victoriaMetrics庫布隆過濾器初始化及使用詳解的詳細內容,更多關於victoriaMetrics庫布隆過濾器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45