Redis里那些统计数据的招数,怎么用才算靠谱又高效
- 问答
- 2026-01-24 13:24:38
- 2
直接说Redis里统计数据的招数,怎么用才靠谱又高效。
首先得明白,Redis不是万能的数据库,它是个内存里的快手,最适合干那些需要快、而且数据可以丢一点、或者能重新算出来的统计活儿,要是你的统计要求百分百精确、还得永久存着,那可能得想想别的办法,或者把Redis和别的数据库搭着用。
第一招:用HyperLogLog估个数,省内存大王。
这招是统计独立用户(UV)这种“去重计数”的神器,比如你想知道一个页面今天有多少不同的人看过,把每个访问者的ID存下来再去重,数据量一大就非常占地方,HyperLogLog的厉害之处在于,它只用固定12KB左右的内存,就能估算出上亿的唯一值,误差率还不到1%,用法很简单,用PFADD命令把元素(比如用户ID)加进去,用PFCOUNT命令看估算值。(这个算法的原理和实现,在Redis的作者Salvatore Sanfilippo的博客和论文里都有深入讨论,它基于概率统计,并非Redis独创,但Redis将其做成了一个非常易用的命令。) 但记住,它是“估算”,不是精确值,而且你不能取出里面具体的ID,适合那些“大概齐”就行、追求极致内存效率的场景。
第二招:用位图(Bitmap)记状态,小空间办大事。
位图其实就是字符串,但你可以把它看成是一串二进制位(0或1),每个用户只占一个位,太省了,最典型的用法是记录用户的签到情况,比如把一年的天数对应成365位,用户第100天签到了,就用SETBIT命令把对应位置设为1,统计签到天数用BITCOUNT,想知道连续签到了多久可以用BITPOS。(在Redis官方文档的“位图”章节中,详细介绍了这些命令,并给出了像“用户在线时间”、“实时指标”等应用思路。) 但要注意,如果用户的ID非常稀疏(比如用户ID是10亿,但只有100个用户),直接用位图可能会浪费空间,因为Redis会为中间的空位分配内存,这时候可能需要对用户ID进行映射。
第三招:用有序集合(Sorted Set)排座次,实时排行榜必备。
这个太常用了,游戏得分排行榜、视频热度排名、销量TOP10,都离不开它,用ZADD把成员和分数加进去,分数可以更新,自动就排好序了,取TOP N用ZREVRANGE,看某个用户的排名用ZREVRANK。(在《Redis实战》这本书里,作者Josiah L. Carlson用了一整章来讲如何用有序集合构建排行榜、时间线等,还讨论了如何避免“冷数据”常驻内存的问题。) 它的高效在于,插入和排序是同时完成的,查询排名和范围查询的速度都很快,但要注意,如果成员数量极其庞大(比如上亿),并且频繁更新,内存和性能压力会增大,有时需要按时间分片,比如做“日榜”、“周榜”。
第四招:用字符串(String)的INCR系列,简单计数快如闪电。
统计网页点击量、文章阅读数、用户点赞数,这种简单的递增递减,用INCR、INCRBY命令再合适不过,因为Redis是单线程执行命令,所以这个操作天生就是原子性的,不会出现并发错误,速度极快。(Redis官方文档在“字符串”数据类型部分明确指出,INCR命令是原子操作,可用于计数器。) 但这里有个“靠谱”的讲究:如果这个数非常重要,不能丢,那你得确保Redis配置了持久化(比如AOF),否则服务器一重启,数字就没了,如果数量特别巨大,可以考虑定期将Redis里的计数同步到持久化数据库中,做个备份。
第五招:用哈希(Hash)存对象,统计多字段关联数据。
比如你要统计一个用户的各种行为次数:点赞数、评论数、转发数,与其为每个行为建一个键,不如用一个哈希表,键是用户ID,字段是行为类型,值是次数,用HINCRBY来增加某个行为的计数,这样管理起来方便,也能减少键的数量。(在《Redis设计与实现》一书中,黄健宏详细分析了哈希表这种数据结构在Redis内部如何实现,以及它在存储对象时的内存优势。) 但要注意,如果这个哈希表的字段爆炸式增长(比如有几万个),那么HGETALL这样的取全部命令可能会比较慢,尽量用HMGET只取需要的字段。
怎么用才算靠谱又高效?总结几点:
- 想清楚能不能接受“估算”和“丢失”:HyperLogLog是估算,位图和计数器如果没持久化可能丢,能接受,就用,换来的是极高的性能和极低的内存消耗。
- 键名设计要讲策略:别乱起名,比如统计日活,键名可以设计成
dau:20231027,这样一目了然,也方便用KEYS或SCAN模式化清理过期数据,避免使用巨大的键(比如一个集合里放几亿成员),考虑分片。 - 利用过期时间(TTL)自动清理:很多统计数据是有时效的,比如一小时内的在线用户,给键设置一个
EXPIRE时间,让Redis自动删除,省去你手动管理的麻烦,也避免内存无限增长。 - 别让一个命令堵死所有人:像
KEYS *、对超大集合做SMEMBERS这种命令,在生产环境要绝对避免,统计大位图的BITCOUNT、大集合的SCARD,虽然本身很快,但如果非常频繁地执行,也可能有影响,考虑在低峰期执行,或者用主从架构,在从库上跑这些统计命令。 - 组合使用,解决复杂问题:比如想统计“今天在线并且完成了某个任务的用户数”,可以结合位图(记录在线)和集合(记录完成任务用户),用
BITOP命令的“与”操作,对两个位图求交集,再BITCOUNT,就能高效得到结果。
用Redis做统计,核心思想是用内存换速度,用算法换空间,接受一定的不精确和可丢失性,把它当成一个超级快的临时工或计算器,而不是一个稳妥的档案管理员,把它的特长用在刀刃上,配合其他数据库,才能构建出既靠谱又高效的系统。

本文由称怜于2026-01-24发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/85108.html
