首页/数据/数据库速查/KEYS 与 SCAN 的取舍(禁止线上 KEYS)
Redis 命令96 条

KEYS 与 SCAN 的取舍(禁止线上 KEYS)

KEYS pattern 全量匹配会阻塞 Redis(O(N) 且单线程),生产禁用;SCAN 游标渐进遍历,虽有重复返回但安全。

数据库速查数据更新于 2026-10-13

KEYS 与 SCAN 是什么

KEYS pattern 一次遍历全库所有键做模式匹配,复杂度 O(N) 且在单线程上跑,线上执行会阻塞所有请求;SCAN 是游标式渐进遍历,每次调用只扫一部分并返回下一个游标,走完返回 0。SCAN 的代价是弱一致:遍历期间被修改的键可能重复返回或被跳过,但它不会长时间阻塞服务。

基本信息

KEYSO(N) 全量扫描,阻塞服务,生产禁用
SCAN每次调用摊到 O(1),整体 O(N),可中断
返回结构第一个元素是下次游标,第二个是键数组
COUNT 参数提示每次扫描的元素个数,默认 10,不保证精确
MATCH 参数在已扫描元素上过滤,不减少整体遍历量

典型使用场景

  • 按前缀清理缓存:SCAN 分批找出键后逐个删除
  • 巡检统计:抽样统计键的类型、过期时间与内存占用
  • 替代 KEYS:任何需要按模式找键的线上操作都应改写为 SCAN
  • 精确计数:写入时维护 SET 或 Hash 索引,避免用 SCAN 做实时统计
  • 容量分析:定时抽样后用 MEMORY USAGE 估算大 key 分布
  • 灰度检查:确认某批业务键是否存在残留,为下线提供依据

安全遍历

安全遍历
SCAN 0 MATCH user:* COUNT 100
# 返回:1) "512"   2) 1) user:1  2) user:9 ...
SCAN 512 MATCH user:* COUNT 100   # 用返回的游标继续,直到游标为 0
# COUNT 是提示量不是精确条数;MATCH 是扫描后过滤,整体仍是全库遍历
# 危险(仅限本地离线小库):
KEYS user:*
# Redis 7.0 起可用 SCAN TYPE hash 只扫指定类型的键

三种取键方式对照

方式阻塞风险适用场景
KEYS高,全库单线程扫描仅限本地或离线小库排障
SCAN低,分批渐进执行线上按模式找键与巡检
维护索引集合无额外扫描开销需要精确计数与实时查询的场景
线上执行 KEYS 是大忌:几十万个键就可能造成秒级阻塞;需要按前缀找键就用 SCAN,或在写入时维护索引结构。
SCAN 不保证遍历期间键集合不变时的一致性:可能重复返回也可能漏掉,所以清理逻辑必须幂等,删除前先确认键的业务归属。

易错点

  • 在线上跑 KEYS *,实例被阻塞数秒,所有业务请求同时超时
  • 把 SCAN 的 COUNT 当作返回条数上限,写出一版错误的分页逻辑
  • 遍历期间有大量写入却假设结果精确,用 SCAN 结果直接做业务决策
  • 忘记用返回的游标继续迭代,只跑一次就以为拿到了全部键
  • 清理脚本不幂等,重复键导致同一业务对象被删两次或误删在用数据

数据来源与参考

  • Redis 官方文档: SCAN
  • Redis 官方文档: KEYS

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌