Redis統(tǒng)計訪問量的3種實現(xiàn)方式
一、你是否遇到過這些統(tǒng)計難題?
- 高并發(fā)場景下內存爆炸:用Hash統(tǒng)計日活時,單鍵內存占用飆升到10MB?
- 獨立訪客重復計數(shù):用戶多次訪問被重復統(tǒng)計,導致UV數(shù)據(jù)虛高?
- 近似值誤差過大:百萬級PV統(tǒng)計時,誤差率超過5%?
這些問題,Redis的3種核心方案能幫你解決!
二、方案一:Hash結構實時統(tǒng)計
適用場景:
- 實時統(tǒng)計獨立用戶(如日活/周活)
- 需要精確計數(shù)(如商品點擊次數(shù))
核心代碼:
# 場景:記錄用戶訪問時間戳(防重復計數(shù))
pipeline.hset("user:visits:202310", user_id, time.time())
pipeline.expire("user:visits:202310", 86400) # 每天清理一次
# 統(tǒng)計當前活躍用戶數(shù)
current_uv = redis.hlen("user:visits:202310")參數(shù)說明:
hset:哈希表存儲用戶ID和最后訪問時間expire:自動清理過期數(shù)據(jù),避免內存泄漏- 痛點解決:通過時間戳去重,精確統(tǒng)計獨立用戶
內存優(yōu)化技巧:
- 問題:10萬用戶ID存儲需約
100KB * 10^5 = 10GB - 方案:使用
user_id:md5縮短鍵名,內存占用可降低至**<1MB/萬用戶**
三、方案二:BitMap統(tǒng)計獨立訪客
適用場景:
- 億級用戶規(guī)模的UV統(tǒng)計
- 內存敏感場景(如單機統(tǒng)計全站訪問量)
核心代碼:
# 場景:統(tǒng)計本月訪問過的用戶(假設用戶ID為整數(shù))
user_id = 123456
redis.setbit("uv:202310", user_id, 1)
# 獲取本月UV總數(shù)
total_uv = redis.bitcount("uv:202310")參數(shù)說明:
setbit:將用戶ID對應位設為1,每個用戶僅占1bit內存bitcount:統(tǒng)計所有置位位數(shù),時間復雜度O(1)
內存對比:
方法 | 100萬用戶內存占用 | 精度 |
|---|---|---|
Hash | ~100MB | 100% |
| BitMap | ~125KB | 100% |
四、方案三:HyperLogLog估算UV
適用場景:
- 超大規(guī)模近似統(tǒng)計(如全網(wǎng)日活)
- 可接受誤差的場景(誤差率<0.8%)
核心代碼:
# 場景:統(tǒng)計全站日活(誤差率0.5%)
redis.pfadd("uv:202310", user_id)
estimated_uv = redis.pfcount("uv:202310")參數(shù)說明:
pfadd:將用戶ID加入HyperLogLog結構pfcount:返回近似值,內存占用僅<1KB/百萬用戶
性能對比:
方法 | 1000萬用戶內存 | 統(tǒng)計誤差 |
|---|---|---|
BitMap | 1.25MB | 0% |
| HyperLogLog | <1KB | 0.5% |
五、實戰(zhàn)選擇指南
對比表格:
方案 | 內存占用 | 精度 | 適用場景 |
|---|---|---|---|
| Hash | 中(MB級) | 100% | 小規(guī)模精確統(tǒng)計 |
| BitMap | 極低(KB級) | 100% | 大規(guī)模精確去重 |
| HyperLogLog | 超低(KB級) | <1% | 超大規(guī)模近似統(tǒng)計 |
優(yōu)化建議:
- 混合方案:用Hash統(tǒng)計小時級數(shù)據(jù),用HyperLogLog匯總日級數(shù)據(jù)
- 數(shù)據(jù)分片:對億級用戶ID按user_id % N分片存儲,降低單鍵內存壓力
- 冷熱分離:歷史數(shù)據(jù)定期轉儲到MySQL,Redis僅保留活躍數(shù)據(jù)
六、總結
Redis統(tǒng)計訪問量的本質是內存優(yōu)化+算法選型的平衡。
- 痛點場景:用BitMap解決內存爆炸,用HyperLogLog應對超大規(guī)模
- 實時需求:Hash結構仍是精確統(tǒng)計的首選
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Redis出現(xiàn)(error)NOAUTH?Authentication?required.報錯的解決辦法(秒懂!)
這篇文章主要給大家介紹了關于Redis出現(xiàn)(error)NOAUTH?Authentication?required.報錯的解決辦法,對于 這個錯誤這通常是因為Redis服務器需要密碼進行身份驗證,但客戶端沒有提供正確的身份驗證信息導致的,需要的朋友可以參考下2024-03-03
詳解RedisTemplate下Redis分布式鎖引發(fā)的系列問題
這篇文章主要介紹了詳解RedisTemplate下Redis分布式鎖引發(fā)的系列問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
詳解redis在服務器linux下啟動的相關命令(安裝和配置)
這篇文章主要介紹了redis在服務器linux下的啟動的相關命令(安裝和配置),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08

