*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:* |
*最佳实践
- 大 Sorted Set 遍历:成员 > 5000 时禁用 ZRANGE 0 -1,用 ZSCAN 分批。
配合 MATCH:过滤特定前缀的 member。
游标不可回溯:ZSCAN 的游标只能向前推进,不能随机跳跃或回退。
遍历期间允许修改: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 分批读取更稳妥,避免阻塞。