2016-10-27
几周前应该工作的需要,使用开源的bloomfilter(避免重复造轮子,自己也懒....),起初做了简单测试,发现没有问题,
就开始正式使用了,几天前无意中发现久远数据新出现,于是就产生了各种怀疑......自己程序问题?多个程序同时跑的问题?
等等!
最后排除代码问题后,开始怀疑使用的bloomfilter有问题,于是开始简洁测试环境,阅读bloomfilter源码,添加调试,
各种测想各种搞,两天时间无果(自己智商太低).
最终找到了问题所在,
先直接上代码:
bloomfilter查询接口:
146 func (bf *bloomFilter) Exists(b []byte) bool {
147
148 for _, s := range bf.Salts {
149 bf.H.Reset()
150 bf.H.Write(s)
151 bf.H.Write(b)
152
153 if bf.Filter.get(uint32(uint64(bf.H.Sum32())%bf.Bits)) == 0 {
154 dlog.Info("==============%d %s", s, str(b))
155 return false
156 }
157 }
158
159 return true
160 }
其实问题就在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重入了,这样出现了错误!