容器级渐进遍历
SCAN 家族用于渐进式遍历大容器:HSCAN 遍历 Hash 字段、SSCAN 遍历 Set 成员、ZSCAN 遍历 ZSet 成员。它们与 HGETALL、SMEMBERS、ZRANGE 0 -1 的区别在于单次调用只返回一部分元素,靠游标分批拉取,避免一次性返回几十万元素把主线程长时间占住。每个命令都要传入游标,返回结果的第一项是下次要用的游标,返回 0 表示遍历结束。
基本信息
| 命令 | HSCAN / SSCAN / ZSCAN key cursor |
|---|---|
| 常用选项 | MATCH pattern、COUNT n;部分版本有 NOVALUES |
| 返回结构 | 先返回下一游标,再返回元素列表 |
| ZSCAN 特点 | 成员与分数交替返回 |
| 一致性 | 遍历期间元素可能重复返回,需要自行去重 |
典型使用场景
- 导出大 Hash 的全部字段做离线分析,分批读取避免阻塞线上请求
- 统计大 Set 的成员规模与分布,替代 SMEMBERS 的全量拉取
- 巡检大 ZSet 的分数分布,发现异常分数(如排行榜里的负数或空成员)
- 缓存预热时按容器逐批写回,把压力摊平到多次调用上
- 大 key 治理:先用 SCAN 定位候选键,再用类型相关的 SCAN 逐层下钻确认
示例
示例
redis-cli HSCAN user:big 0 COUNT 100 # 第一轮,游标从 0 开始
redis-cli HSCAN user:big 1234 COUNT 100 # 用上一轮返回的游标继续
redis-cli HSCAN user:big 0 MATCH 'name*' COUNT 100 # 只取字段名匹配的项
redis-cli ZSCAN rank:big 0 COUNT 100 # 成员与分数交替返回
redis-cli SSCAN tags:big 0 COUNT 100
# 游标返回 0 时表示遍历结束,此时才可停止返回结构逐列读法
| 位置 | 含义 | 注意 |
|---|---|---|
| 第 1 项 | 下一次遍历要用的游标 | 为 0 才表示结束,不是空结果 |
| 第 2 项起 | 元素列表 | HSCAN 为字段与值交替,ZSCAN 为成员与分数交替 |
| MATCH | 服务端过滤模式 | 被过滤掉的元素同样占用本次遍历量 |
| COUNT | 单次尝试扫描的元素上限 | 是提示值,实际返回可能多于或少于它 |
遍历期间容器如果被并发修改,可能返回已经见过的元素,也可能漏掉新增元素;对一致性要求高的导出任务,应结合版本号、时间戳或双跑校验来确认完整性。
HSCAN 的 NOVALUES 选项在较新版本才提供,旧版本执行会直接报语法错误;脚本里用到版本相关选项时,先在目标实例上确认版本。