這是一個建立於
的文章,其中的資訊可能已經有所發展或是發生改變。
2016-10-27
golang bloomfilter踩過的坑(https://github.com/mmczoo/dgobloom)
幾周前應該工作的需要,使用開源的bloomfilter(避免重複造輪子,自己也懶....),起初謝了簡單測試,發現沒有問題,
就開始正式使用了,幾天前無意中發現久遠資料新出現,於是就產生了各種懷疑......自己程式問題?多個程式同事跑的問題?
等等!
最後排除代碼問題後,開始懷疑使用的bloomfilter有問題,於是開始簡潔測試環境,閱讀bloomfilter源碼,添加調試,
各種測想各種搞,兩天時間無果(自己智商太低).
最終找到了問題所在,
先直接上代碼:
bloomfilter查詢介面:
146 func (bf *bloomFilter) Exists(b []byte) bool {147148 for _, s := range bf.Salts {149 bf.H.Reset()150 bf.H.Write(s)151 bf.H.Write(b)152153 if bf.Filter.get(uint32(uint64(bf.H.Sum32())%bf.Bits)) == 0 {154 dlog.Info("==============%d %s", s, str(b))155 return false156 }157 }158159 return true160 }
其實問題就在bf.H,我們繼續追蹤bf.H:
69 type bloomFilter struct {...... 74 H hash.Hash32 `json:"h"` 75 Salts [][]byte `json:"salts"` 76 }
我使用的H是fnv.New32a():
53 bf := bloom.NewBloomFilter(bloomConf.BFCap, bloomConf.BFfpr, fnv.New32a(), salts) 38 func New32a() hash.Hash32 { 39 var s sum32a = offset32 40 return &s 41 }
其實就是定義了一個uint32的新資料類型,注意這裡是&s.
現在大家應該知道Exists中的bf.H問題了吧,bf.H在這裡是共用資料,不支援重入。
而我們的訪問量很大,導致self.H重入了,這樣出現了錯誤!