平常接需求的時候, PM提出來一個須要統計頁面UV/PV的需求你怎麼作?html
下面有三個選擇:mysql
首先, 選1的時候看公司架構怎麼說, 若是人家給你排期到半個月後了你這需求還作不作了?redis
其次, 選2是咱們的大多數狀況, 並且是最直白的一種統計方式.
這種方式的好處就是統計準確, 且能保留住數據, 在特定的業務裏面還能複用(好比作個ip黑名單, 反做弊啥的).
固然缺點也很明顯, 若是你的服務請求量特別大, 那麼你存儲數據的體積增加特別快. 算法
好比放到redis的集合裏面(曾經我就這麼幹過), 把全部請求的ip存到redis中, 最後統計集合中元素的個數, 後來運維開始在羣裏嚷嚷:我們緩存服務的內存要不夠用啦!
運維把大key一列, 嗯? xx, 你這緩存能優化一下不? 這幾百mb的冷數據扔緩存裏面太浪費資源了balabalasql
總之就是你得優化一下了, 那麼怎麼優化呢? 緩存
bitmap也是一種不錯的方式, 把十進制映射到bit字節上, 好比 10000000 個基數, 那麼轉換後就變成了 100000000/8/1024/1024 ≈ 12M, 這也是個不錯的選擇, 不過key不少的狀況下佔用空間也很多架構
通過我一番谷歌+翻文檔, 發現了這麼個神奇的東西: HyperLogLog, 基於機率這種玄學的算法運維
Redis 在 2.8.9 版本添加了 HyperLogLog 結構, 它的優點就是每一個key僅需12kb的內存, 就能存儲 2^64 個不一樣元素的基數, 存儲空間小且固定, 缺點就是元數據沒法直接提取了post
這種是基於機率的算法, 既然是機率就包含着不肯定性, 存在統計偏差, 不過大部分場景是能hold住的, 若是須要絕對精確的狀況, 不要用這個大數據
使用的命令以下:
127.0.0.1:6379> PFADD test_uv id1 id2 id3 id4 id1 (integer) 1 127.0.0.1:6379> PFCOUNT test_uv (integer) 4 127.0.0.1:6379> PFADD test_uv2 id1 id2 id5 (integer) 1 127.0.0.1:6379> PFMERGE test_uv3 test_uv test_uv2 OK 127.0.0.1:6379> PFCOUNT test_uv3 (integer) 5
PFADD 添加基數
PFCOUNT 統計個數
PFMERGE 兩個key合併
就是這麼簡單, 粗暴
這個我也是看的別人的, 因此就把這兩篇文章列出來本身複習一下: