首页/数据/Redis 进阶速查/HSCAN/SSCAN/ZSCAN 遍历容器元素
性能与排障129 条

HSCAN/SSCAN/ZSCAN 遍历容器元素

对 Hash/Set/ZSet 使用对应 SCAN 家族命令渐进遍历大容器,避免 HGETALL/SMEMBERS 一次性返回海量元素造成阻塞。

Redis 进阶速查数据更新于 2026-10-13

容器级渐进遍历

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 选项在较新版本才提供,旧版本执行会直接报语法错误;脚本里用到版本相关选项时,先在目标实例上确认版本。

易错点

  • 把 COUNT 当成精确返回条数,据此写分页或进度逻辑,导致数据对不上
  • 没判断游标是否为 0 就提前退出循环,拿到的是不完整数据
  • 在超时敏感的同步调用里用超大 COUNT,单次扫描仍然耗时,超时重试还会重复读取
  • 用 SCAN 家族替代 KEYS 方向正确,但大规模遍历本身也是负载,应避开业务高峰执行

数据来源与参考

  • Redis 官方文档:HSCAN / SSCAN / ZSCAN 命令
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌