Redis统计访问量的3种实现方式
更新时间:2025年06月10日 09:39:47 作者:Java程序员 拥抱ai
这篇文章主要介绍了Redis统计访问量的3种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
一、你是否遇到过这些统计难题?
- 高并发场景下内存爆炸:用Hash统计日活时,单键内存占用飙升到10MB?
- 独立访客重复计数:用户多次访问被重复统计,导致UV数据虚高?
- 近似值误差过大:百万级PV统计时,误差率超过5%?
这些问题,Redis的3种核心方案能帮你解决!
二、方案一:Hash结构实时统计
适用场景:
- 实时统计独立用户(如日活/周活)
- 需要精确计数(如商品点击次数)
核心代码:
# 场景:记录用户访问时间戳(防重复计数) pipeline.hset("user:visits:202310", user_id, time.time()) pipeline.expire("user:visits:202310", 86400) # 每天清理一次 # 统计当前活跃用户数 current_uv = redis.hlen("user:visits:202310")
参数说明:
hset
:哈希表存储用户ID和最后访问时间expire
:自动清理过期数据,避免内存泄漏- 痛点解决:通过时间戳去重,精确统计独立用户
内存优化技巧:
- 问题:10万用户ID存储需约
100KB * 10^5 = 10GB
- 方案:使用
user_id:md5
缩短键名,内存占用可降低至**<1MB/万用户**
三、方案二:BitMap统计独立访客
适用场景:
- 亿级用户规模的UV统计
- 内存敏感场景(如单机统计全站访问量)
核心代码:
# 场景:统计本月访问过的用户(假设用户ID为整数) user_id = 123456 redis.setbit("uv:202310", user_id, 1) # 获取本月UV总数 total_uv = redis.bitcount("uv:202310")
参数说明:
setbit
:将用户ID对应位设为1,每个用户仅占1bit内存bitcount
:统计所有置位位数,时间复杂度O(1)
内存对比:
方法 | 100万用户内存占用 | 精度 |
---|---|---|
Hash | ~100MB | 100% |
BitMap | ~125KB | 100% |
四、方案三:HyperLogLog估算UV
适用场景:
- 超大规模近似统计(如全网日活)
- 可接受误差的场景(误差率<0.8%)
核心代码:
# 场景:统计全站日活(误差率0.5%) redis.pfadd("uv:202310", user_id) estimated_uv = redis.pfcount("uv:202310")
参数说明:
pfadd
:将用户ID加入HyperLogLog结构pfcount
:返回近似值,内存占用仅<1KB/百万用户
性能对比:
方法 | 1000万用户内存 | 统计误差 |
---|---|---|
BitMap | 1.25MB | 0% |
HyperLogLog | <1KB | 0.5% |
五、实战选择指南
对比表格:
方案 | 内存占用 | 精度 | 适用场景 |
---|---|---|---|
Hash | 中(MB级) | 100% | 小规模精确统计 |
BitMap | 极低(KB级) | 100% | 大规模精确去重 |
HyperLogLog | 超低(KB级) | <1% | 超大规模近似统计 |
优化建议:
- 混合方案:用Hash统计小时级数据,用HyperLogLog汇总日级数据
- 数据分片:对亿级用户ID按user_id % N分片存储,降低单键内存压力
- 冷热分离:历史数据定期转储到MySQL,Redis仅保留活跃数据
六、总结
Redis统计访问量的本质是内存优化+算法选型的平衡。
- 痛点场景:用BitMap解决内存爆炸,用HyperLogLog应对超大规模
- 实时需求:Hash结构仍是精确统计的首选
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
CentOS7.5使用mysql_multi方式安装MySQL5.7.28多实例(详解)
这篇文章主要介绍了CentOS7.5使用mysql_multi方式安装MySQL5.7.28多实例,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下2020-01-01
最新评论