# 15. Redis ZSet(有序集合)底层实现及排行榜设计

# 标准答案

Redis ZSet(Sorted Set) 采用 跳表(SkipList)+ 哈希表(Hash Table) 进行存储。

  • 跳表 维持有序性,支持 O(logN) 级别 范围查询、排名计算
  • 哈希表 提供 O(1) 快速访问,用于查找成员是否存在及其分数。

ZSet 可高效实现 排行榜、积分榜、点赞榜、搜索权重排序 等场景,支持 ZADDZRANGEZREVRANK 等操作。

# 答案解析

# 1. ZSet(Sorted Set)底层结构

ZSet = 跳表(SkipList)+ 哈希表(Hash Table)

  • 跳表(SkipList)
    • 维护 有序结构,支持 范围查询(ZRANGE),时间复杂度 O(logN)
    • 采用 多级索引,加快查询效率,适用于大规模数据排序。
  • 哈希表(Hash Table)
    • 通过 Key → Score 映射,快速查询元素是否存在,O(1) 复杂度。
    • 适用于 ZSCOREZINCRBY 操作。

📌 两者结合:跳表提供排序和排名,哈希表提供快速访问。

# 2. Redis ZSet 如何实现排行榜

ZSet 适用于 积分排行榜、点赞排行榜、搜索权重排序 等。

# (1)插入数据

ZADD leaderboard 100 "Alice"
ZADD leaderboard 200 "Bob"
ZADD leaderboard 150 "Charlie"
1
2
3
Rank 用户 Score
1 Bob 200
2 Charlie 150
3 Alice 100

# (2)获取排行榜

# 🔹 获取 Top N 排名

ZREVRANGE leaderboard 0 2 WITHSCORES
1
  • ZREVRANGE分数从高到低 排序。
  • WITHSCORES 显示分数。

# 🔹 查询用户排名

ZREVRANK leaderboard "Alice"
1
  • 返回 Alice 排名(索引从 0 开始)。

# 🔹 查询用户积分

ZSCORE leaderboard "Charlie"
1

# (3)排行榜进阶优化

需求 Redis 命令
增加分数(加分机制) ZINCRBY leaderboard 10 "Alice"
删除用户(离开榜单) ZREM leaderboard "Alice"
获取分数区间排名(筛选 Top 100) ZCOUNT leaderboard 100 200
删除过期数据(限制榜单大小) ZREMRANGEBYRANK leaderboard 100 -1

# 3. 跳表(SkipList)实现细节

跳表是 Redis ZSet 的核心数据结构,相比 红黑树,跳表的 代码更简单、插入删除更高效

# 跳表结构

  • 多层索引 提高查询效率,类似于跳跃搜索。
  • 每个节点随机决定是否提升到更高层,类似于高速公路+普通公路的设计。
  • 时间复杂度:插入/查询/删除 O(logN),比 O(N) 的链表快。

📌 示例:ZSet 数据插入

ZADD leaderboard 300 "Tom"
1

跳表结构(示例)

Level 3:     Tom
Level 2:     Tom ----> Bob
Level 1:     Tom ----> Bob ----> Charlie
Level 0:     Tom ----> Bob ----> Charlie ----> Alice
1
2
3
4
  • 查询 Tom 需要 1 次跳跃,查询 Alice 需要 3 次跳跃。

# 4. ZSet vs. Set vs. List

结构 适用场景 排序 访问速度
ZSet 排行榜、搜索权重 ✅ 有序 O(logN) 查询
Set 去重、共同关注 ❌ 无序 O(1) 查询
List 消息队列、聊天记录 ✅ 按插入顺序 O(N) 查询

# 深入追问

  1. Redis 跳表 vs. 红黑树,为什么选择跳表?
  2. 如何优化百万级排行榜?(分片、缓存方案)
  3. ZSet 适合排行榜,但不适合什么场景?
  4. 如果要存储 1 亿条数据的实时排行榜,如何优化?
  5. 如何实现基于时间衰减的动态排行榜?

# 相关面试题

  • Redis ZSet 如何存储大规模用户排名数据?
  • ZREVRANK vs. ZRANK 的区别?
  • 如何用 Redis ZSet 实现“最近热搜”榜?
  • ZSet 操作如何进行高并发优化?
  • ZSet 存在大 Key 时,如何拆分优化?

# 总结

  1. ZSet 采用 跳表+哈希表 结合,支持 O(logN) 排名计算,适用于排行榜、积分榜等场景。
  2. 跳表比红黑树更简单,插入/查询效率更高。
  3. Redis 提供 ZADDZREVRANKZINCRBY 等指令,可高效操作排名数据。
  4. 排行榜场景可结合缓存、定期清理、分片优化,提升性能。
  5. ZSet 适用于有序数据排名,但不适用于高频写入的场景(如实时日志)。