溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用

發(fā)布時間:2021-12-06 14:02:21 來源:億速云 閱讀:215 作者:小新 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用,小編覺得挺實(shí)用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

在我們做站點(diǎn)流量統(tǒng)計(jì)的時候一般會統(tǒng)計(jì)頁面UV(獨(dú)立訪客:unique visitor)和PV(即頁面瀏覽量:page view),那么我們最常見的處理方式就是用戶點(diǎn)擊一次就插入一條數(shù)據(jù)到數(shù)據(jù)庫,統(tǒng)計(jì)的時候通過查詢表來達(dá)到統(tǒng)計(jì)流量的效果。

那么我們?nèi)绻峭ㄟ^redis來處理,我們可以使用string類型然后自增計(jì)數(shù)即可達(dá)到統(tǒng)計(jì)PV,統(tǒng)計(jì)UV可以使用set,每個用戶id是唯一的可以放到這個集合里,統(tǒng)計(jì)的時候只需要執(zhí)行scard獲取集合大小即可。

這兩種方式都是可以實(shí)現(xiàn)站點(diǎn)的流量統(tǒng)計(jì),但是如果說當(dāng)站點(diǎn)流量非常大每天幾千萬次的訪問量,那么數(shù)據(jù)庫可能就要分表分庫了,redis添加足夠多的數(shù)據(jù)后內(nèi)存消耗也是非常驚人的,總的來說這樣做是不劃算的,那么我們的redis有一種專門處理這樣數(shù)據(jù)的算法,HyperLogLog。

HyperLogLog基本使用方式

HyperLogLog提供了兩個指令pfadd和pfcount,根據(jù)字面意思很好理解,一個是增加計(jì)數(shù),一個是獲取計(jì)數(shù)。pfadd和set集合的sadd的用法是一樣的,pfcount和scard的用法是一樣的,直接獲取計(jì)數(shù)值。

HyperLogLog還提供一個合并的指令pfmerge,用于將兩個pf累加形成一個新的pf,如果說我們需要將每個頁面的流量合并,那么我們這個指令大有用處。

> pfadd user mango(integer) 1> pfadd user zhangsan(integer) 1> pfadd user lisi(integer) 1> pfadd user mango     #重復(fù)則不計(jì)數(shù)(integer) 0> pfcount user(integer) 3
> pfadd paper mango(integer) 1> pfadd paper zhangsan(integer) 1> pfmerge pv user paper    #合并OK> pfcount pv(integer) 3

注意:

  1. HyperLogLog的計(jì)數(shù)統(tǒng)計(jì)是有一定的誤差的,誤差最大在1%以下。

  2. HyperLogLog數(shù)據(jù)結(jié)構(gòu)需要占據(jù)12KB的存儲空間,所以我們在使用的時候得注意,如果數(shù)據(jù)量非常小我們可以選擇其他方式,但是如果是數(shù)據(jù)量非常大,那么我們這個數(shù)據(jù)結(jié)構(gòu)就非常有價(jià)值了。但是我們也不要太過于擔(dān)心它的消耗,一開始初始的時候是沒有這么大的,在計(jì)數(shù)比較小時他是采用稀疏矩陣來進(jìn)行存儲,空間占用率還是很小的,只有到達(dá)一定閾值后才會轉(zhuǎn)變成稠密矩陣空間才會到達(dá)12KB。

命令pf前綴的由來

Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用

我們使用這個HyperLogLog命令的時候有點(diǎn)奇怪的感覺,因?yàn)槲覀兪褂胔ash的時候都是h開頭hadd,set都是sadd,zset都是z開頭,那么我們的HyperLogLog為啥是個pf呢?HyperLogLog這個數(shù)據(jù)結(jié)構(gòu)的發(fā)明人Philippe Flajolet, pf 是他的名字的首字母縮寫。
HyperLogLog實(shí)現(xiàn)原理  

HyperLogLog實(shí)際上不會存儲每個元素的值,它使用的是概率算法,通過存儲元素的hash值的第一個1的位置,來計(jì)算元素?cái)?shù)量。

Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用

我們第一次產(chǎn)生的隨機(jī)值獲取到它的二進(jìn)制,從右往左計(jì)數(shù)連續(xù)0的個數(shù),每次獲取這個數(shù)出現(xiàn)1和0的概率都是1/2,k在任意回合出現(xiàn)的概率即為(1/2)^k,因此可以推測n=2^k,但是一般來講n的值會在2^k和2^k之間徘徊,為了要讓這個算法更加準(zhǔn)確,于是引入了桶的概念,計(jì)算m個桶的加權(quán)平均值,這樣就能得到比較準(zhǔn)確的答案了(實(shí)際上還要進(jìn)行其他修正)。最終的公式如圖

Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用

其中m是桶的數(shù)量,const是修正常數(shù),它的取值會根據(jù)m而變化。p=log2m

switch (p) {   case 4:       constant = 0.673 * m * m;   case 5:       constant = 0.697 * m * m;   case 6:       constant = 0.709 * m * m;   default:       constant = (0.7213 / (1 + 1.079 / m)) * m * m;}

HyperLogLog相關(guān)的命令有三個:

pfadd hll ele:將ele添加進(jìn)hll的基數(shù)計(jì)算中。流程:

  1. 先對ele求hash(使用的是一種叫做MurMurHash的算法) 

  2. 將hash的低14位(因?yàn)榭偣灿?的14次方個桶)作為桶的編號,選桶,記桶中當(dāng)前的值為count

  3. 從的hash的第15位開始數(shù)0,假設(shè)從第15位開始有n個連續(xù)的0(即前導(dǎo)0)

  4. 如果n大于count,則把選中的桶的值置為n,否則不變

pfcount hll:計(jì)算hll的基數(shù)。就是使用上面給出的DV公式根據(jù)桶中的數(shù)值,計(jì)算基數(shù)

pfmerge hll3 hll1 hll2:將hll1和hll2合并成hll3。合并方法是將所有的HyperLogLog對象合并到一個名為max的對象中,max采用的是密集存儲結(jié)構(gòu),如果被合并的對象也是密集存儲結(jié)構(gòu),則循環(huán)比較每一個計(jì)數(shù)值,將大的那個存入max。

Redis的所有HyperLogLog結(jié)構(gòu)都是固定的16384個桶(2的14次方),并且有兩種存儲格式:

  • 稀疏格式:HyperLogLog算法在剛開始的時候,大多數(shù)桶其實(shí)都是0,稀疏格式通過存儲連續(xù)的0的數(shù)目,而不是每個0存一遍,大大減小了HyperLogLog剛開始時需要占用的內(nèi)存

  • 緊湊格式:用6個bit表示一個桶,需要占用12KB內(nèi)存

pf 的內(nèi)存占用為什么是 12k?  
 我們在上面的算法中使用了1024個桶進(jìn)行獨(dú)立計(jì)數(shù),不過在Redis的HyperLogLog實(shí)現(xiàn)中用到的是16384個桶,也就是2^14,每個桶的maxbits需要6個bits來存儲,最大可以表示maxbits=63,于是總共占用內(nèi)存就是2^14 * 6/8 = 12k 字節(jié)。

關(guān)于“Redis站點(diǎn)流量統(tǒng)計(jì)HyperLogLog怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)
推薦閱讀:
  1. 怎么用redis
  2. redis怎么用

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI