統計計數和HyperLogLog數據類型


最近還是想好好打下基礎,先看看redis,參考gitbook上面的《Redis開發運維實踐指南》。看到HyperLogLog類型,有點懵逼,看了書里面推薦的文章,大概是一知半解了,mark一下。

簡介

HyperLogLog是一種可以實現計數問題的方案或者說算法,redis實現了HyperLogLog,把HyperLogLog作為一種數據類型/結構。

解決問題:計數問題(計算集合的基數)

優點:占用空間小,1.5K可以對十億級的數據進行計數(2%的誤差)

缺點:基於hash的統計計數(我這么翻譯的,英文叫probabilistic counters),有誤差

 

計數問題

給定一個值空間S,有N個元素,給定一個行為,會決定一個/批元素是否進入一個該空間的子集Sub,我們需要計算出經過任意次行為后這個子集Sub中包含的元素個數C。

PS:我也不知道原始的問題是怎么定義,自己瞎比定義一下

 

計數方案

方案一:使用hash表或者集合(set)

N個元素,需要k=ceil(log2N)位來表達,存滿N個元素,需要kN位,量級是0(kN)。將問題具體一下,一個系統有1億用戶,每個用戶的標識至少是27bit,就是4B。至少需要4B*227 = 229B≈500M。同理10億用戶約為4B*230=4G。考慮到大多數系統的用戶id,都是留了很多冗余空間的,再加上,數據結構本身占用的空間,一個Set或者Hash表保存十億用戶id占用的空間往往是幾十G。

優點:計數精確。

缺點:占用空間較大。數據量大時,幾乎不可行。

 

方案二:使用bitmap

使用bitmap,需要一個合適的hash函數配合。可以大幅降低占用空間,但是十億數據,大概也要百M(10億/8B≈128M)級別的空間。

優化:使用稀疏bitmap,可以使占用的空間隨C的大小變化。

優點:十億數據占用空間在0M~100M間波動,隨C越大,占用空間越大。

    方便進行位操作

缺點:計數量大時還是占用了100M空間,而且依賴Hash算法,存在少量沖突。

 

方案三:使用統計計數

通過以上描述,計數問題的難點也差不多說明白了。這個問題在很多應用中都存在,比如點贊統計,比如點擊(觀看、訪問)XX的用戶數統計等等。

幸運的是,我們有統計計數方案,來作為以上方案的補充。我們回到一道小學數學題。

問:一個池塘里有很多魚,隨機抓100條,打上標記,放回去。再隨機撈100條,有N條帶標記的魚,請問池塘里大概有多少條魚。

解:100/x = n/100,x=100*100/n。

如果有一種隱射方式將N個數隨機映射到M個數上(M<<N),我們隨機把這C個數也隱射一下,數量記為MC,C≈N*MC/M。由於M遠小於N,所以這個隱射肯定是無法做到1對1映射,所以肯定有誤差。

 

小結

本質上,三種方案都使用了映射。方案一將一個數據映射成了log2Nbit,方案二將一條數據映射為了1bit,而方案三將多條數據映射為了1bit。億級數據情況下,三種方案的比較如下。

  Hash/Set Bitmap

probabilistic counters

空間 G級(10G) M級(100M) K級(10K)
誤差 0 極低(可忽略) 百分位
可行性 幾乎不可行 可行 條件可行

條件可行意為,是否能接受百分位的誤差,如果接受就可行,不接受就不可行。

 

統計計數probabilistic counters

上面提到統計計數方案,只是用了一種最簡單的統計方法,是本人自行理解的一種方案。大神們肯定有更優化的方案,主要有線性統計計數(Linear Probabilistic Counter)、HyperLogLog。參考http://highscalability.com/blog/2012/4/5/big-data-counting-how-to-count-a-billion-distinct-objects-us.html。

當然了,如果有興趣,可以翻一翻相關的文章,應該會有收獲。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM