Redis里模糊删除到底怎么能快点,性能瓶颈在哪儿还有啥优化空间
- 问答
- 2026-01-02 05:01:42
- 2
关于Redis里模糊删除(也就是使用 KEYS 模式匹配 后再删除,或者直接用 SCAN 加 DEL)怎么能快点,性能瓶颈在哪儿,还有啥优化空间,我们得先搞清楚它为什么慢。
核心瓶颈:Redis的单线程模型 最根本的一点,Redis在处理命令时是单线程的(指其核心网络模型和键值操作),这是所有问题的总根源,它像一个只有一个收银员的超市,不管来了多少顾客,都得排队一个一个来,任何一条命令如果执行时间很长,都会堵住后面所有的命令,导致整个服务“卡住”,模糊删除操作,恰恰就是一种非常容易“耗时很长”的操作。
第一个大坑:KEYS 命令
KEYS 这个命令是问题最大的,当你在一个包含几百万甚至更多键的Redis上执行 KEYS user:* 时,Redis会怎么做呢?它会遍历整个数据库的所有键,一个一个地去比对是否符合你给的模式,这个遍历过程是同步的、不能中断的,在它吭哧吭哧遍历的这几秒钟甚至更长时间里,Redis这个“收银员”就完全停下了手里所有其他工作,专门为你找钥匙,这期间,其他所有读写请求全部超时,对线上业务来说就是灾难。在任何生产环境中,都绝对禁止使用 KEYS 命令,这不是快慢的问题,是能不能用的问题。
改进方案:SCAN 命令
为了解决 KEYS 的阻塞问题,Redis提供了 SCAN 命令。SCAN 的好处是增量式、游标式的遍历,它一次只返回一小部分匹配的键(比如几百个),然后给你一个游标,你下次带着这个游标再来,它再从上次停下的地方继续找,这样就把一个长时间的阻塞,打散成了很多个非常短暂的“微阻塞”。
SCAN 只是“不那么卡”了,并不代表“快”,它的性能瓶颈依然存在:
- 遍历的成本没变:虽然每次只返回一小部分,但为了找到这些键,Redis底层仍然需要遍历整个键空间,如果数据库非常大,完成一次完整的
SCAN循环(直到游标返回0),总耗时依然很长,只是这个耗时被分摊开了。 - 删除操作(DEL)本身也是瓶颈:当你通过
SCAN拿到一批键后,通常要用DEL命令删除它们,如果你一个一个地DEL,每删除一个都是一次网络往返和一条命令执行,对于大量键的删除,这种频繁的请求本身就会成为性能瓶颈,并且会占用很多网络资源。
如何优化才能更快? 既然知道了瓶颈在于“单线程”和“大量命令操作”,优化的方向就很明确了:减少对主线程的占用,以及将多个操作合并。

-
使用
UNLINK代替DEL这是最重要、也是最容易实施的优化,从Redis 4.0开始,提供了UNLINK命令。DEL命令是同步删除,立刻回收内存,主线程会等待删除完成,而UNLINK不同,它只是把键从键空间里“摘除”,真正的内存回收工作会交给后台的专门线程去异步处理,这样,执行UNLINK命令的主线程耗时极短,可以迅速回去处理其他请求,大大降低了删除操作对服务的影响。在绝大多数需要批量删除的场景下,都应该无脑选择UNLINK。 -
使用管道(Pipeline) 当你用程序循环执行
SCAN和DEL/UNLINK时,每次循环都是一次网络往返(Round-Trip Time, RTT),对于成百上千次的删除,网络延迟会占据很大一部分时间,使用管道(Pipeline)技术,可以将多个DEL/UNLINK命令打包成一个请求发送给Redis,Redis再将所有结果打包返回,这极大地减少了网络往返次数,能提升数倍甚至数十倍的效率。 -
Lua脚本(谨慎使用) 你可以写一个Lua脚本,在脚本内部完成
SCAN和DEL,因为Lua脚本在Redis中是原子执行的,它能保证在脚本执行期间,不会有其他命令插队,也避免了并发问题。Lua脚本本身也是单线程执行的!如果一个Lua脚本执行时间过长,它和KEYS命令一样会阻塞整个服务器,除非你非常确定要删除的键数量很少,否则不推荐在Lua脚本中进行大规模的扫描和删除,它更适合小规模的、需要原子性的批量操作。
-
终极武器:设置过期时间,让其自动淘汰 这是最治本、对性能影响最小的方案,如果你的业务逻辑允许,不要手动去删除键,而是在创建键的时候就直接给它设置一个过期时间(TTL),缓存数据可以设置几分钟或几小时的TTL,这样,Redis会在后台惰性删除+定期删除的策略下,自动清理过期的键,这个清理过程是Redis自身维护的,对前台业务几乎无感,这完全避免了在某个时间点进行大规模删除操作带来的性能冲击。
-
从架构上思考:分片(Cluster) 如果你的Redis是集群模式,数据被分散到了多个节点上,当你执行模糊删除时,压力也会被分摊到不同的节点,在每个节点上,需要扫描的键数量变少了,删除的操作也分散了,这相当于多了几个“收银员”同时干活,这需要你的客户端支持向所有节点广播
SCAN命令,或者你自己写脚本来遍历所有分片。
总结一下优化路径:
- 绝对禁止使用
KEYS。 - 基础操作:使用
SCAN+UNLINK。 - 网络优化:对
UNLINK命令使用管道(Pipeline)打包。 - 治本之策:对临时数据优先设置过期时间,让Redis自己清理。
- 大规模环境:利用集群分片特性分摊压力。
- 谨慎选择:仅在删除量极小时考虑Lua脚本以保证原子性。
归根结底,优化Redis模糊删除的核心思想就是:敬畏它的单线程特性,想尽一切办法减少单次操作对主线程的占用时间,把大的、重的任务拆小、化整为零、或者扔到后台去。
本文由帖慧艳于2026-01-02发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/72881.html
