Redis计数器其实挺好用的,简单几步就能搞定怎么用才最有效呢?
- 问答
- 2025-12-30 13:49:19
- 4
行,那我直接给你聊聊Redis计数器怎么用最有效,这事儿其实不难,但里面有些小门道,用对了能省不少心。
先说说它最基本的用法,简单到不行,你就把它想象成一个放在内存里的数字盒子,速度飞快,比如你要统计网站的总用户数,传统做法可能是查数据库,SELECT COUNT(*) FROM users,用户一多,这查询就慢,还费数据库资源,用Redis就简单了,来个命令 INCR total_users,每注册一个新用户,就执行一次这个命令,这个 total_users 键的值就自动加1,你要看总数?直接用 GET total_users,瞬间就拿到结果,完全不用去碰数据库,这种场景下,它的效果立竿见影。(这个基本思路在很多技术博客里都有提到,算是入门级用法)
但光会加1可不够,现实情况复杂得多,你要统计的是今天的活跃用户数,而不是从开站以来的总数,这时候,键的设计就很重要了,你不能永远用同一个 total_users,得让它“带时间”,你可以把键设计成 active_users:20231027(假设今天是2023年10月27日),这样,每天都是一个独立的计数器,到了第二天,再用 active_users:20231028,清清楚楚,互不干扰,统计某天的数据直接取那天的键就行了。

还有一种更常见的需求是统计用户个人的某些次数,比如某个用户一天内发了多少条帖子,或者请求某个API的频率,这常用于防止恶意刷帖或攻击,这时候,键就要把用户ID和日期都包进去,user_post_count:12345:20231027(12345是用户ID),每次用户发帖前,你先 INCR 这个键,然后马上用 GET 看一下值是多少,如果超过了你设定的上限(比如每天100帖),就直接拒绝发帖,提示“今日发帖次数已用完”,这里有个关键点,INCR和GET这两个操作最好能一口气完成,也就是保证原子性,不然可能出问题,虽然分开执行在大多数时候没事,但在高并发下,可能你INCR完,另一个请求也INCR了,你再GET到的值可能就已经超了,更稳妥的做法是使用Redis的管道(pipeline)或者Lua脚本,把多个命令打包执行,确保中间不会被别的命令插队。(这种防刷逻辑在电商秒杀、API限流中非常普遍)
说到限流,这是Redis计数器一个超级实用的高级玩法,除了上面按天、按用户限制,更精细的是滑动窗口限流,限制一个IP地址一分钟内只能请求60次API,按自然分钟切分可能不够平滑,比如在59秒时来了60个请求,下一秒刚开始又来60个,瞬间压力会很大,滑动窗口的意思是,我永远只看当前时间往前推一分钟内的请求数,实现起来稍微复杂点,可以用Redis的有序集合(Sorted Set)来做,但单纯用计数器也能模拟个大概,你可以设置一个键,并给它一个过期时间(比如60秒),每次请求来了就 INCR 这个键,如果这是第一次请求(INCR后返回1),同时给它设置60秒后过期,后续每次INCR后检查值,超过60就限流,这样,这个计数器就代表了最近60秒内的请求量,窗口随着时间在滑动,虽然不如有序集合精确,但胜在简单高效,对很多场景来说已经够用了。

别忘了给计数器设置过期时间,这是非常关键的一步,能帮你自动清理没用的数据,防止Redis被这些临时性的计数键占满内存,像上面提到的按天统计的键,完全可以设置一个7天的过期时间,保留最近一周的数据供查询就够了,用 EXPIRE 命令或者在设置值时直接用 SETEX 都能搞定,养成随手设置过期时间的习惯,能让你后续的运维轻松很多。
任何技术都不能脱离实际,Redis是内存数据库,数据存在内存里,虽然它有自己的持久化机制(RDB快照和AOF日志),但毕竟不像硬盘那么“牢靠”。用Redis计数器存的数据,最好是那种允许丢失的、或者丢了也能快速重建的,比如实时在线人数、一分钟内的API调用次数,这种数据丢了影响不大,重新开始计数就好,但如果是非常重要的财务数据,比如订单总数,那最好还是以数据库的最终数据为准,Redis的计数器可以作为一个性能极佳的实时缓存来用,定期与数据库同步一下。
想让Redis计数器发挥最大效果:一是键要设计好,把业务场景(比如用户ID)、时间维度都包含进去;二是活用过期时间,做好内存管理;三是理解原子操作,在需要严格保证顺序的地方用管道或Lua脚本;四是认清数据特性,把它用在合适的场景,把这些点琢磨透了,这个小小的计数器就能帮你解决很多大数据量下的实时统计难题。
本文由凤伟才于2025-12-30发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/71300.html
