cuckoo filter 簡介

    介紹個小東西, cuckoo filter (布穀鳥過濾器)。可以用作替代bloom filter。
    
    介紹這個東東前先簡單介紹一下 cuckoo hash。 cuckoo hash 是一種hash表, 在最壞情況下查找也是常數時間, 它主要是在 hash 衝突時處理方法比較特殊。傳統hash表在發生hash衝突的時候, 通過把衝突的item掛在一張鏈表上解決(當然還有其它方式, 這裏不討論), 在查詢時需要遍歷這個鏈表。 這樣最壞情況下查詢時間其實是不確定的。而cuckoo hash。 把一個hash表分成相等的兩份, 採用兩個hash函數記作h1(.), h2(.)。 這樣任何一個key 通過h1和h2可以計算得到2個bucket。這個key就一定存在這兩個bucket中。 查找的時候, 至多查找兩次。插入數據時, 看這兩個bucket是否爲空, 如果任何一個空閒, 插入就好了, 如果都不空閒, 則挑一個bucket, 把當前值插入到這個bucket中, 把bucket中原來的值踢出來。 把被踢出來的值, 插入這個被踢出值的另外一個bucket中。 如果那個bucket空閒則插入結束, 否則踢出原有值, 反覆這個過程。因爲算法如同布穀鳥下蛋一樣, 找個巢就下蛋, 如果巢裏已經有蛋了, 就把原有的蛋從巢裏踢出去, 所以叫做cuckoo hash。下面這個圖從維基百科上拷貝過來的, 說明了這個插入過程。
k h(k) h'(k)
20 9 1
50 6 4
53 9 4
75 9 6
100 1 9
67 1 6
105 6 9
3 3 0
36 3 3
39 6 3


1. table for h(k)
20 50 53 75 100 67 105 3 36 39
0
1 100 67 67 67 67 100
2
3 3 3 36
4
5
6 50 50 50 50 50 105 105 105 50
7
8
9 20 20 20 20 20 20 53 53 53 75
10
2. table for h'(k)
20 50 53 75 100 67 105 3 36 39
0 3
1 20 20 20 20
2
3 36 39
4 53 53 53 53 50 50 50 53
5
6 75 75 75 75 75 75 67
7
8
9 100 100 100 100 105
10

    cuckoo hash 適合大併發的讀, 少量的寫的應用場景。 而且空間利用率可以做到很高。 如果你有足夠的空間, 以至於hash 衝突基本不發生, 這東西對你沒用。

    下面介紹 cuckoo filter。不清楚 bloom filter的同學請先補一下bloom filter知識。cuckoo filter裏不會存儲原信息, 只存儲指紋信息, 那麼在一個iterm被擠出, 需要重新找位置的時候, 怎麼計算這個iterm的另外一個位置呢(沒有原來的key, 知道兩個hash函數也沒法計算)?cuckoo 採用只需要指紋信息就能找到第二個bucket的方式, 技巧在這裏:
    i1= HASH(x),
    i2= i1 ⊕HASH(x′s fingerprint)
    其中 ⊕ 是異或運算。所以:
    j = i ⊕HASH(fingerprint)
    也就是說, 知道了當前的bucket(i), 知道指紋信息, 就可以計算出另外一個bucket(j)。
    要從cuckoo filter裏刪除一個元素, 只需要從cuckoo hash裏查到這個元素匹配的指紋, 從表中刪除即可。這是因爲即便有兩個元素, 他們的指紋信息相同, 並且計算得到的i1也相同(從而i2必然也相同), 按照剛纔的方式刪除也是安全的。當另外的元素來查找的時候, 仍然能夠查到。
    這裏有一點要注意, 如果要支持刪除, 當插入重複數據的時候, 每次都需要存儲一次指紋信息。這很容易造成插入的失敗, 所以要限制重複數據的插入, 如果不支持刪除則無此問題。
    原文裏提到爲了提高hash表的佔用率(occupancy), 在一個bucket下存儲多個指紋是非常有效的, 當然這要增加查找時候的比較次數同時增加指紋的長度來保持false postive的比率(可以這樣理解, 一個bucket存放更多的指紋, 可以降低hash表本身的大小, hash表減小, 其實降低了區分度, 增加指紋長度, 又提高了區分度)。他們測試的平衡點是每個bucket存4個指紋。
    關於指紋信息, 稍微提一下, 大家不要一下子想到128位md5. 存儲是需要成本的, 所以這裏的指紋可能就是一個12bits。 指紋位數的確定和影響, 請見原文。
    當一個cuckoo hash表中元素達到一定量的時候, 插入就很容易失敗, 這時需要擴展hash表來容納更多元素。 但是對於bloom filter來說, 可以一直插入元素, 不過這時 false postive的比率會很高(基本就失去作用了), 如果要保持這個合理的比率 bloom filter也需要擴展。

    原文可以通過 cuckoo filter:better than bloom 搜索到, 請希望瞭解更多細節的同學自行查看原文。


    

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
閱讀(1) | 評論(0) | 轉發(0) |
給主人留下些什麼吧!~~
評論熱議
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章