轉載請代表出處算法
對 布隆過濾器 畫個重點,它應該在 「過濾」 二字上,這個算法的重點在於把曾經來過跟從將來過的事物區分開,具體過濾那種事物(曾經來過or從將來過),由具體場景決定。它通常用於數據庫存儲中過濾不存在的行(減小訪問磁盤),推薦系統去重等等場景。數據庫
說到去重,很容易想到STL中的SET容器,它自己自帶去重功能,並且還能查詢。
那麼最簡單的方式,直接用SET。每次操做的時候,先查詢該事物是否存在?app
具體以下圖所示:.net
這種方式準確率是絕對準確的,可是這種方式耗費的內存也是巨大的。
假設每一個事物須要 K 字節,那麼若是有 M 個事物,一共須要 K * M 字節。那麼咱們能不能縮小這裏的內存呢?
稍微損失一點準確率換取內存?具體見下面HashMap的方式blog
在上一種方式中,它存儲了具體的事物信息,其實在咱們這個場景中是不須要的。咱們須要的只是這個事物是否存在就好了,因此HashMap的方式誕生了。
這種算法在每次操做的時候,先查詢該事物是否存在,內存
衆所周知,hash都是有必定機率衝突的,並且當哈希桶快滿的時候,衝突率更高。
接下來咱們來看看這裏的衝突率有多少?假設哈希桶長度爲M,那麼每次插入到特定一個桶的機率是:$$(1-\frac{1}{M})$$
而沒有插入特定桶的機率是:$$1-(1-\frac{1}{M})$$
而後假設目前已經插入N個事物,那麼特定桶中爲0的機率是:$$(1-\frac{1}{M})^N$$
特定桶中爲1的機率是:$$1-(1-\frac{1}{M})^N$$get
假設如今要新插入一個事物,此次插入的衝突率就是:hash
因此這裏在N接近M的時候,衝突率是很高的,這種算法就徹底失效了。
有沒有辦法解決這種狀況呢?布隆過濾器能下降這裏衝突率。class
布隆過濾器是用了多hash的方式下降了衝突率的。
這種算法在每次操做的時候,先查詢該事物在K個hash桶中是否都存在,容器
接下來咱們來看看這種有K個Hash加持的算法,衝突率有多少?假設哈希桶長度爲M,那麼每次插入到特定一個桶的機率是:$$K (1-\frac{1}{M})$$
而沒有插入特定桶的機率是:$$(1-(1-\frac{1}{M}))^K$$
而後假設目前已經插入N個事物,那麼特定桶中爲0的機率是:$$(1-\frac{1}{M})^{NK}$$
特定桶中爲1的機率是:$$1-(1-\frac{1}{M})^{NK}$$
假設如今要新插入一個事物,此次插入的衝突率就是:
因爲這裏有K次方的加持,它的衝突率小不少的。
通常來講,在使用布隆過濾器的時候,N是由場景已經決定了的,怎麼選擇M跟K呢?
P爲衝突率
因爲布隆過濾器都是直接置1,因此它根本沒法刪除一個事物的。有沒有辦法支持它刪除+統計個數呢?
想要刪除特定事物,那其實也很簡單。
直接把布隆過濾器的位存儲改爲數字存儲就好了。
那麼在每次操做的時候,跟布隆過濾器差異的點在於:
這種算法是已經支持刪除+統計了,相應的它的內存佔用可不是翻倍這麼簡單的。 不一樣的場景用不一樣的算法吧,最合適的纔是效果最好滴。