日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

从BloomFilter到Counter BloomFilter

發布時間:2023/11/27 生活经验 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从BloomFilter到Counter BloomFilter 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 前言
    • 1. Traditional BloomFilter
    • 2. Counter BloomFilter

本文traditional bloomfilter 和 counter bloomfilter的C++實現 均已上傳至:
https://github.com/BaronStack/BloomFilter

前言

Bloomfilter 是一個老生常談的數據結構,應用在存儲領域的各個系統之中,用來準確判斷一個字符串是否不存在,高效判斷一個字符串是否存在,有容錯率

詳細描述和代碼實現均已上傳至github中,本文簡單描述一下原理和關鍵代碼。

1. Traditional BloomFilter

傳統的BloomFilter實現 就是針對輸入的一個字符串列表 作為我們的數據集。
對其中的每一個字符串 通過一個或者多個hash函數生成一個唯一的hash值,將這個值映射到bloomfilter上,把bloomfilter維護的一個bit序列相關的bit位置1。

如下 bloom filter維護的一個bit序列:

第一個string 通過hash 函數 生成的hash值,映射到bloomfilter的三個bit位中,將對應的bit位置1

第二個string 通過同樣的hash函數生成一個唯一的hash值,映射到同一個bloomfilter的bit位中,已經為1的就不用置位了

依此,后續的字符串在構造bloom filter的時候都通過如上方式來構造,這樣一個數據集只需要完成一次構造。

后續拿著構造好的bit序列來檢測輸入的string,只需要通過hash函數拿到hash值就能夠 通過O(1)的時間(位運算)精確匹配這個輸入的string不存在(hash值映射的bit位為0,說明肯定不存在,存在的話之前通過hash值映射的就為1)。

看看如下代碼 構造bloomfilter :

// CreateFilter:根據輸入的key 批量構建bloom filter
// 參數1: keys, 輸入的需要構造成bloomfilter的string列表
// 參數2: n,輸入的元素個數
// 參數3: dst 最終的bloomfilter結果
//
// 這里的構造邏輯是通過雙hash算法實現的,
// 針對輸入的string 先生成一個uint32_t 的hash值
// 再針對其中的num_probe_個bit位進行置1
void BloomFilter::CreateFilter(std::string* keys,int n, std::string *dst ) {size_t bits = n * bits_per_key_; // bits_pter_key_表示需要維護的bloomfilter的位數if(bits < 64) {bits = 64;}size_t bytes = (bits + 7) / 8;bits = bytes * 8;const size_t init_size = dst->size();dst->resize(init_size + bytes, 0);dst->push_back(static_cast<char>(num_probe_));  // Remember # of probeschar* array = &(*dst)[init_size];// Use double-hashing to generate a sequence of hash values.// 這里使用雙hash算法來生成hash值// See analysis in [Kirsch,Mitzenmacher 2006].for(size_t i = 0;i < static_cast<size_t>(n); i++) {uint32_t h = hash_func_(keys[i]);const uint32_t delta = (h >> 17) | (h << 15);for (size_t j = 0; j < num_probe_; j++) {const uint32_t bitpos = h % bits;array[bitpos/8] |= (1 << (bitpos % 8)); // 將bitpos位置置為1h += delta;}}
}

通過如上構造的bloomfilter 來匹配對應的key,輸入的key是否存在于bloomfilter之中

// 檢查輸入的key 是否存在于構造的bloom filter 之中
bool BloomFilter::KeyMayMatch(std::string key, std::string& bloom_filter){const size_t len = bloom_filter.size();if (len < 2) return false;const char* array = bloom_filter.c_str();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 = hash_func_(key);const uint32_t delta = (h >> 17) | (h << 15);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;
}

2. Counter BloomFilter

Counter Blooomfilter的應用場景是 我們想要動態變更構造好的bloomfilter,比如從bloomfilter中刪除一個key的映射。這樣我們之前說的traditional bloomfilter的設計就無法實現了,畢竟bit只有一個值,且可能被多個key的hash映射公用。

這個時候可以維護一個counter(下面的代碼是一個uint32_t的數值表示上面traditional的bit位,當然也可以uint8_t),按照之前的方式來構造,對每一個輸入的key生成一個hash值, 這個hash值映射到bloomfilter之上,讓對應的"bit"位自增即可。刪除其中的key映射的時候,可以讓對應的bit位自減少。

輸入第一個string時保持各個bit位為1

當輸入第二個時,string的hash值映射到同一個bit,則讓bit位數值++即可:

后續的字符串構造過程中類似,也是針對匹配的’bit’位自增即可:

構造過程的實現代碼如下:

// CreateCounterFilter: 創建一個計數功能的bloomfilter
// 參數1:keys ,輸入多個string類型 的字符串
// 參數2: n, 輸入的字符串串長度
// 參數3: 根據輸入的字符串構造出來的計數bloom filter
//
// 原理如下:
// 維護一個uint32_t 的數組,其中每一個元素代表一個bit位
// 0 0 0 0 0 ... 0 0 0
//
// add string1 --> hash_func
//          |
//          |
// 0 1 0 1 1 ... 1 0 0
//
// add string2 --> hash_func
//          |
//          |
// 1 2 1 1 2 ... 1 0 1
//
// 如果想要從構造的bloom filter中刪除string1,則只需要讓hash_func
// 的對應 "bit" 位的數值-1 即可
// remove string1 --> hash_func
//          |
//          |
// 1 1 1 0 1 ... 0 0 1
void CounterFilter::CreateCounterFilter(std::string* keys, int n,vector<uint32_t> *dst) {size_t bits = n* bits_per_key_;// 構造一個存放 uint32_t的bloomfilter數組 -- dstif(bits < 32) {bits = 32;}size_t bytes = (bits + 7) / 8;bits = bytes * 8;const size_t init_size = dst->size();dst->resize(bits, 0);uint32_t* array = &(*dst)[init_size];for(size_t i = 0;i < static_cast<size_t>(n); i++) {uint32_t h = hash_func_(keys[i]);vector<BITTYPE> bit_types;Bitcount(h, &bit_types);for(size_t j = 0; j < bit_types.size(); j++) {if(bit_types[j].is1) {array[bit_types[j].bit_pos] ++;}}}
}

需要注意的是Counter bloomfilter需要針對每一個bit位用更多的字節表示,所以Counter Bloomfilter會消耗更多的內存。

相關代碼完整實現均已上傳至:
https://github.com/BaronStack/BloomFilter

總結

以上是生活随笔為你收集整理的从BloomFilter到Counter BloomFilter的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。