Redis ZSet(有序集合)

返回 Redis

ZSet(Sorted Set) 为每个 member 关联一个 score(双精度浮点),按 score 排序。member 唯一,同一 member 重复 ZADD 会更新 score。是 排行榜、延迟队列、滑动窗口限流 的首选结构。


完整命令表见 基础命令 · ZSet

ZADD rank:daily 9500 user:1001 8800 user:1002
ZINCRBY rank:daily 200 user:1001
ZREVRANGE rank:daily 0 9 WITHSCORES          # Top 10
ZREVRANK rank:daily user:1001

底层结构

  • 每个 ZSet:跳表(skiplist) + 哈希表(member → score),保证 O(log N) 范围查询与 O(1) 查分。
  • member 较长或元素极多时注意内存;单 key 元素过多会成为热 key。

典型场景

排行榜

Key 设计memberscore
rank:game:20240601userId积分/步数
rank:friend:{uid}:20240601friendId好友榜

更新:ZINCRBYZADD(覆盖为最新值)。
完整方案:排行榜与实时计数点赞计数

延迟队列

score = 执行时间戳(毫秒),定时任务 ZRANGEBYSCORE delay 0 now LIMIT n 取出到期 member 再 ZREM

ZADD delay:queue 1718000000000 job:1001
ZRANGEBYSCORE delay:queue 0 1718000100000 LIMIT 0 10

滑动窗口限流

score = 请求时间戳,member = 唯一请求 id;窗口内 ZCOUNT 或先 ZREMRANGEBYSCORE 删过期再计数。

热搜 / 权重时间线

score 可编码「热度 + 时间衰减」;注意与 热搜 的缓存层级配合。


设计注意

问题处理
分数相同member 字典序 二级排序,非插入顺序
并列排名业务若要「并列第 1」需自行处理 rank 显示
热 key大榜拆分为 rank:shard:0… 或只缓存 Top N
持久化大 ZSet RDB/AOF 重写成本高,控制单 key 规模
与 Set 区别Set 无 score;去重用 Set,排序用 ZSet

ZSet vs Hash

需求选型
只要对象字段Hash
要排序、TopN、按分数范围ZSet

集群

  • 一个 ZSet 一个 key → 单 slot;不支持跨 key 的 ZSet 分片(除非业务拆 key)。
  • ZUNIONSTORE 多 key 时要求 same slot(可用 hash tag:rank:{uid}:daily)。

Spring Boot

redisTemplate.opsForZSet().add("rank:score", "player1", 9500);
redisTemplate.opsForZSet().incrementScore("rank:score", "player1", 200);
Set<ZSetOperations.TypedTuple<Object>> top10 =
    redisTemplate.opsForZSet().reverseRangeWithScores("rank:score", 0, 9);
Long rank = redisTemplate.opsForZSet().reverseRank("rank:score", "player1");

详见 Redis 集成


相关链接