*Redis SCAN 命令

以游标方式分批遍历 key,不阻塞 Redis 主线程。


*语法

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]

*参数说明

参数 类型 必填 说明
cursor Integer 游标,第一次为 0,后续用上一次的返回值
MATCH String 匹配模式,glob 风格
COUNT Integer 每次扫描的槽位数量,默认 10,建议 100-1000
TYPE String 只返回指定类型的 key(Redis 6.0+)

*返回值

返回 [next_cursor, [key1, key2, ...]],next_cursor 为 0 表示遍历完成。


*时间复杂度

O(1) 每次调用 + O(N) 返回 N 个元素。由于 COUNT 控制每次扫描量,单步不阻塞。


*示例

# 基础用法
> SCAN 0
1) "17"
2) 1) "key:12"
   2) "key:8"

> SCAN 17
1) "0"
2) 1) "key:25"
   2) "key:3"

# 带 MATCH 过滤
> SCAN 0 MATCH user:* COUNT 100
1) "42"
2) 1) "user:1001"
   2) "user:1002"

# 带 TYPE 过滤(Redis 6.0+)
> SCAN 0 TYPE hash
1) "5"
2) 1) "config:app"

*常见错误

  1. 游标处理错误:游标不是递增的,不能按页码处理。必须用上一次返回的游标值。
  2. COUNT 过小:COUNT 默认 10,扫描大实例时需要大量次循环。建议 COUNT 100-1000。
  3. 遍历期间数据变化:SCAN 不保证返回最新数据,不保证不重复/不遗漏。业务需兼容。

*最佳实践

  1. 生产环境替代 KEYS:所有遍历场景用 SCAN,设置 COUNT 100-1000 平衡单次开销和总时间。
  2. 批量删除SCAN 0 MATCH old:* COUNT 1000 + DEL 分批删除,避免一次 DEL 太多。
  3. 遍历完所有 key:游标返回 0 时完成,过程中可能出现重复 key,业务层去重。

*FAQ

Q: SCAN 一定会在一次循环内返回 COUNT 个 key 吗? A: 不一定。COUNT 只是给 Redis 的扫描槽位提示,实际返回数量可能多也可能少。

Q: SCAN 遍历期间新增/删除 key 会有问题吗? A: 可能返回重复 key,也可能遗漏极少数 key。不影响绝大多数场景,不要假设结果集精确不变。

Q: 有 HSCAN/SSCAN/ZSCAN 吗? A: 有。分别用于遍历 Hash field、Set member、Sorted Set member,语法与 SCAN 类似。