用Redis怎么搞那个等待时间设置,别太复杂但又能有效控制响应啥的
- 问答
- 2026-01-18 22:25:28
- 2
你想用Redis搞一个等待时间设置,说白了就是想控制某些操作的频率,或者让用户等一等再执行下一个动作,用户发短信验证码,你不能让他一分钟内狂点一百次;又比如,某个抢购活动,你不想让服务器被瞬间涌来的请求冲垮,需要让请求排队等一会儿。
Redis干这个特别拿手,主要是因为它快,而且有几个现成的“小工具”非常适合这种场景,下面就说几个最常用、最直接的办法。
第一个办法,用Redis的SET命令自带的一个神奇参数。
平常我们用的SET key value就是简单的设置值,但Redis给这个命令加了不少“佐料”,其中两个特别有用:NX 和 EX。
NX的意思是“只有当这个key不存在的时候,我才设置它”,如果key已经存在,那这次设置就失败。EX是给这个key设置一个过期时间,单位是秒,时间一到,Redis会自动把这个key删掉。
把这两个结合起来,就能实现一个简单的“锁”或者“冷却计时器”,要控制用户发送短信的间隔不能少于60秒,可以这么干:
当用户请求发送短信时,你执行这样一条命令:SET user_id:123:sms_lock "1" EX 60 NX。

这行命令的意思是:看看Redis里有没有一个叫 user_id:123:sms_lock 的钥匙,如果没有(NX),那我就把它设置成1,并且规定它60秒后自动失效(EX),如果设置成功了,Redis会返回OK,这说明这个用户之前60秒内没发过短信(因为key不存在),那你就可以放心地真正去调用短信接口发短信了。
如果这个用户手快,在60秒内又点了一次发送,你再执行同样的命令,但这次Redis里那个key还在(还没过期),由于加了NX参数,这次设置会失败,Redis会返回nil,你的程序收到这个信号,就知道“哦,这个用户还在冷却期”,直接给他返回一个“操作太频繁,请稍后再试”的提示就行了。
这个方法的精髓在于,判断和设置这两个动作是Redis一条命令原子性完成的,非常可靠,不会出现程序刚判断完key不存在,还没来得及设置,另一个请求也判断为不存在的情况,这个方法超级简单,几行代码就能搞定,非常适合这种单一的频率控制。
第二个办法,用列表(List)来做一个简单的排队系统。
控制频率不只是“允许”或“拒绝”这么简单,你可能想让过来的请求先排好队,然后你的服务端不紧不慢地一个一个处理,这就有点像银行取号,用户拿了号可以等着,而不是被直接拒之门外。

Redis的列表天生就是个队列,你可以用LPUSH命令把请求塞到队列的左边(尾部),然后用BRPOP命令从队列的右边(头部)阻塞地取出请求,这个B代表Block,也就是阻塞。
具体怎么做呢?比如有一个处理起来比较慢的任务,像生成一个复杂的报告。
- 当用户请求生成报告时,你的程序不马上去处理,而是生成一个任务信息(比如包含用户ID、报告类型等),然后用
LPUSH report_queue task_data把这个任务放进名叫report_queue的队列里,做完这个,就可以先快速给用户返回一个“报告正在生成,请稍后查看”的响应。 - 你另外开一个或多个“工人”程序(worker),它们专门负责处理这个队列,工人程序不停地执行
BRPOP report_queue 0,这个命令的意思是:从report_queue队列里取一个任务出来,如果队列是空的,那我就在这儿死等(0代表无限等待),直到有任务进来为止。 - 一旦
BRPOP拿到了一个任务,工人程序就开始吭哧吭哧地处理这个生成报告的任务,处理完了,把结果存到数据库或者另一个Redis键里,并通知用户。
这个方法通过排队,把“立即处理”的压力变成了“慢慢消化”的能力,它有效地控制了后台处理任务的节奏,防止服务器因为瞬间来的太多活而被“噎死”,对于前端用户来说,体验也比直接被告知“服务器忙,请重试”要好。
第三个办法,用有序集合(Sorted Set)搞更高级一点的时间窗口控制。
上面第一个方法只能控制“连续两次操作之间的间隔”,但有时候你的需求可能是“一分钟内最多只能操作5次”,不管这5次是怎么分布的,这就是时间窗口控制。

Redis的有序集合给每个成员都关联一个分数(score),这个分数我们可以用来存时间戳。
假设要限制一个用户一分钟内最多只能点赞5次。
- 当用户点赞时,获取当前的时间戳(比如用毫秒表示),记作
current_time。 - 你执行两条命令:
- 用
ZREMRANGEBYSCORE user_id:123:likes 0 current_time-60000,这条命令的意思是:把有序集合user_id:123:likes中,所有分数(也就是时间戳)在1分钟以前(current_time - 60000毫秒)的成员都删掉,这样就只留下了最近一分钟内的点赞记录。 - 用
ZCARD user_id:123:likes命令,看看清理后这个集合里还有多少个成员(即最近一分钟内他已经点了几次赞)。
- 用
- 如果这个数量小于5,说明他还可以点赞,那你就在用
ZADD user_id:123:likes current_time random_value,把他的这次点赞记录加进去(分数是当前时间戳,成员用一个随机值,比如也可以再用一次时间戳,确保唯一就行)。 - 你可以给整个有序集合设置一个过期时间,比如
EXPIRE user_id:123:likes 60,让Redis在一分钟后自动清理掉这个key,省得积累太多无用数据。
如果ZCARD查出来的数量已经等于或大于5了,那这次点赞请求就要被拒绝。
这个方法比第一个方法稍微绕一点,但它能实现更精细的控制,统计的是某个时间窗口内的总次数,而不是相邻两次的间隔。
- 想要简单粗暴地控制间隔,N秒内不能重复操作”,用SET key value EX N NX,最省事。
- 想要缓解瞬时压力,让请求排队异步处理,用列表(List) 和
LPUSH/BRPOP,体验更好。 - 想要精确控制单位时间内的总次数,每分钟最多N次”,用有序集合(Sorted Set) 配合时间戳来清理和计数,最灵活。
这些就是Redis用来搞等待时间设置最核心、最实用的几种套路了,你可以根据你具体的业务场景,选一个最合适的来用。
本文由革姣丽于2026-01-18发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/83294.html
