KEYS 与 SCAN 是什么
KEYS pattern 一次遍历全库所有键做模式匹配,复杂度 O(N) 且在单线程上跑,线上执行会阻塞所有请求;SCAN 是游标式渐进遍历,每次调用只扫一部分并返回下一个游标,走完返回 0。SCAN 的代价是弱一致:遍历期间被修改的键可能重复返回或被跳过,但它不会长时间阻塞服务。
基本信息
| KEYS | O(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 不保证遍历期间键集合不变时的一致性:可能重复返回也可能漏掉,所以清理逻辑必须幂等,删除前先确认键的业务归属。