leveldb研究系列七——FilterPolicy
来源:互联网 发布:爱因斯坦大脑 知乎 编辑:程序博客网 时间:2024/06/13 18:13
virtual const char* Name() const = 0; // 返回filter的名字
CreateFilter接口,对key创建filter写入det中
virtual void CreateFilter(const Slice* keys, int n, std::string* dst)const = 0;
KeyMayMatch 接口 匹配过滤key
virtual bool KeyMayMatch(const Slice& key, const Slice& filter)const=0;
对于key的过滤策略采用了Bloom filter. Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员,这种检测只会对在集合内的数据错判,而不会对不是集合内的数据进行错判,这样每个检测请求返回有“在集合内(可能错误)”和“不在集合内(绝对不在集合内)”两种情况,可见 Bloom filter 是牺牲了正确率换取时间和空间. 多个独立的hash函数对key计算填写bit。 在验证的时候计算key的hash指向位是否全部填充。 如果否则key不在集合中,否则则有可能在集合中。
leveldb并没有真正给出多个独立的哈希函数,leveldb选择的策略很简单,通过原始hash,位移产生新的哈希值
Leveldb选择的hash函数是:
h += delta
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits在bloom_filter的数据的最后一个字节存放的是k_的值,k_实际上就是计算时采用的hash函数个数。下面是
构造函数代码:
explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) { // We intentionally round down to reduce probing cost a little bit k_ = static_cast<size_t>(bits_per_key * 0.69); // 0.69 =~ ln(2) if (k_ < 1) k_ = 1; if (k_ > 30) k_ = 30; } virtual const char* Name() const { return "leveldb.BuiltinBloomFilter"; }变量k_实际上就是模拟的hash函数的个数,变量bits_per_key_,对于n个key,其hash table的大小就是bits_per_key_。它的值越大,发生冲突的概率就越低,那么bloom hashing误判的概率就越低。因此这是一个时间换空间的策略。
BloomFilter的构建函数如下
virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { // Compute bloom filter size (in both bits and bytes) size_t bits = n * bits_per_key_; //filter的位长度 // For small n, we can see a very high false positive rate. Fix it // by enforcing a minimum bloom filter length. if (bits < 64) bits = 64; //长度不能太小 否则容易碰撞 size_t bytes = (bits + 7) / 8; bits = bytes * 8; //取到N个字节数 const size_t init_size = dst->size(); dst->resize(init_size + bytes, 0); //分配空间 dst->push_back(static_cast<char>(k_)); // Remember # of probes in filter char* array = &(*dst)[init_size]; for (size_t i = 0; i < n; i++) { // Use double-hashing to generate a sequence of hash values. // See analysis in [Kirsch,Mitzenmacher 2006]. uint32_t h = BloomHash(keys[i]); const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits //模拟产生k个哈希函数 for (size_t j = 0; j < k_; j++) { const uint32_t bitpos = h % bits; array[bitpos/8] |= (1 << (bitpos % 8)); // 在bits array上设置第bitpos位 h += delta; } } }Bloom filter已经构建完成。(哈希函数,再哈希)
BloomFilter的匹配过程相对简单
计算key的hash值,计算全部hash,只要filter上的相应位是0则返回false,匹配结束。对于结果为true表明可能在集合中,如果为false则一定不在集合中.
virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { const size_t len = bloom_filter.size(); if (len < 2) return false; const char* array = bloom_filter.data(); const size_t bits = (len - 1) * 8; // Use the encoded k so that we can read filters generated by // bloom filters created using different parameters. const size_t k = array[len-1]; if (k > 30) { // Reserved for potentially new encodings for short bloom filters. // Consider it a match. return true; } uint32_t h = BloomHash(key); const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits for (size_t j = 0; j < k; j++) { const uint32_t bitpos = h % bits; if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false; h += delta; } return true;
到此为止,我们已经分析好leveldb的bloomfilter的过滤策略,这是典型的用时间换空间的买卖。
- leveldb研究系列七——FilterPolicy
- leveldb研究系列三——log文件系统
- leveldb研究系列四——memtable组件
- leveldb研究系列五——Ssttable组件
- leveldb研究系列二——各个组件和读写时序介绍
- leveldb研究系列六——Block的组件构建和读取
- leveldb研究系列八——Ssttable文件的compaction和LRUcache
- levelDB—初识levelDB
- leveldb研究系列一 .leveldb的简单介绍和简单使用
- leveldb研究系列一 .leveldb的简单介绍和简单使用
- leveldb(七):Memtable
- leveldb研究 - 编译/调试
- leveldb研究5- Snapshot
- hadoop深入研究:(七)——压缩
- hadoop深入研究:(七)——压缩
- hadoop深入研究:(七)——压缩
- hadoop深入研究:(七)——压缩
- hadoop深入研究:(七)——压缩
- 机器视觉的一些链接
- Linux Shell编程入门
- 当感觉自己写的代码表达不够清晰,有些bad smell时应该怎么做?
- 吐槽poj1062(不是解题报告,没有代码,仅仅吐糟)
- java第三周作业,P45 -3
- leveldb研究系列七——FilterPolicy
- 用编程工具实现数据可视化的几个选择
- 黑马程序员-java基础加强-JDK1.5新特性
- Response对象的encodeURL原理
- web.xml文件向后台传值
- php pack unpack
- java随机生成一个n bit位的长质数
- eclipse中.java文件批量修改字符集
- Ubuntu下的ssh设置