zrank 返回升序排名(最小分索引0),zrevrank 返回降序排名(最大分索引0),时间复杂度均为o(log n);成员不存在时返回nil而非-1,需判空处理;同分时按member字典序确定排名。

ZRANK 返回升序排名,ZREVRANK 返回降序排名
Redis 的 ZRANK 和 ZREVRANK 都是 O(log N) 时间复杂度的命令,但返回的值含义相反:ZRANK 从最低分(score 最小)开始数,索引为 0;ZREVRANK 从最高分(score 最大)开始数,同样索引为 0。两者都只查 member 是否存在,不关心 score 是否重复 —— 若 score 相同,Redis 按字典序(member 字符串)排序补位。
成员不存在时返回 nil,不是 -1
这是最容易踩的坑:当 zrank myzset "nonexistent" 执行时,返回的是 (nil)(Redis CLI 显示),不是整数 -1。很多客户端(如 redis-py、jedis)会把 nil 转成 None 或 null,若代码里直接做算术运算(比如 +1 判断“是否在前10”),会抛出空指针或类型错误。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 检查前务必用
if rank is not None:(Python)或Objects.nonNull(rank)(Java)判空 - 不要写
if rank >= 0:——nil无法和数字比较 - 如果业务需要“不存在即排最后”,得自己补逻辑,Redis 不提供默认 fallback
score 相同导致排名“不稳定”,但实际是确定的
例如插入 ZADD myzset 100 "a" 100 "b" 100 "c",再执行 ZRANK myzset "b" 总是返回 1 —— 因为 Redis 内部按 member 字符串字典序排序,"a" 。看起来“不稳定”是因为人没意识到字典序参与了排序,但结果每次都是确定的。
- 不要依赖“插入顺序”来预测同分排名
- 若需严格按插入顺序,得把时间戳或自增 ID 拼进 member 名(如
"b_1724589360"),并确保唯一性 -
ZRANGE myzset 0 -1 WITHSCORES可验证当前实际排序
高并发下 ZRANK/ZREVRANK 本身无竞态,但业务逻辑可能有
这两个命令是只读原子操作,Redis 不加锁也不阻塞,不会因并发变慢或出错。但如果你的代码是“先 ZRANK,再根据排名做 ZREM 或 ZADD”,那两步之间就存在时间窗口 —— 排名可能已变。
- 避免“读-改-写”裸序列,优先用 Lua 脚本封装原子逻辑
- 例如:想把排名超过 100 的 member 删除,别用 client 先查 rank 再发 ZREM,改用
EVAL "... zrank ... zrem ..." ... - 注意 Lua 中
redis.call('ZRANK', KEYS[1], ARGV[1])返回的是字符串或false,需手动转类型
nil 返回值处理和同分时的字典序隐含规则 —— 这两点不提前确认,上线后容易在边界 case 上静默失败。










