*Redis ZSCAN 命令

以游标方式分批遍历 Sorted Set 中的成员。


*语法

ZSCAN key cursor [MATCH pattern] [COUNT count]

*参数说明

参数 类型 必填 说明
key String Sorted Set 的键名
cursor Integer 游标,首次为 0
MATCH String 匹配 member 名
COUNT Integer 扫描提示数量

*返回值

返回 [next_cursor, [member1, score1, member2, score2, ...]]


*时间复杂度

O(1) 每次调用 + O(N) 返回 N 个元素。


*示例

> ZADD leaderboard 100 "p1" 200 "p2" 300 "p3"

> ZSCAN leaderboard 0
1) "0"
2) 1) "p1"
   2) "100"
   3) "p2"
   4) "200"
   5) "p3"
   6) "300"

*常见错误

错误 原因 解决
WRONGTYPE Operation against a key holding the wrong kind of value 对非 Sorted Set 类型执行 ZSCAN 使用 TYPE 命令确认 key 类型为 zset
游标使用错误导致无限循环或遍历异常 cursor 传值不规范 首次调用传入 0,后续使用返回的 next_cursor,不可手动构造
单次阻塞客户端 COUNT 值过大导致单次返回元素过多 合理设置 COUNT(如 100~1000),分批处理
返回结果不符合预期 MATCH 模式语法错误 使用正确的 glob 风格模式,如 user:*

*最佳实践

  1. 大 Sorted Set 遍历:成员 > 5000 时禁用 ZRANGE 0 -1,用 ZSCAN 分批。
  2. 配合 MATCH:过滤特定前缀的 member。

  3. 游标不可回溯:ZSCAN 的游标只能向前推进,不能随机跳跃或回退。

  4. 遍历期间允许修改:ZSCAN 允许遍历期间修改集合,但可能重复返回或遗漏部分元素。

*5. 配合 SSCAN/HSCAN 使用:不同数据结构使用对应的 SCAN 命令,避免混用导致错误。

*FAQ

Q1: ZSCAN 和 ZRANGE 怎么选择? A: 已知排名范围用 ZRANGE;需要遍历全部或不确定范围时用 ZSCAN。

Q2: ZSCAN 返回的游标为 0 表示什么? A: 表示遍历完成。首次调用传入 0,后续使用返回的游标,直到游标再次为 0。

Q3: ZSCAN 能保证遍历期间不重复吗? A: 不能保证。遍历期间集合被修改,可能导致某些元素被重复返回或遗漏。

Q4: COUNT 是精确返回数量吗? A: 不是。COUNT 只是提示数量,实际返回数量可能多于或少于 COUNT。

Q5: ZSCAN 和 ZRANGE 0 -1 哪个更快? A: 小集合 ZRANGE 更快;大集合(>5000)ZSCAN 分批读取更稳妥,避免阻塞。