# 15. Redis ZSet(有序集合)底层实现及排行榜设计
# 标准答案
Redis ZSet(Sorted Set) 采用 跳表(SkipList)+ 哈希表(Hash Table) 进行存储。
- 跳表 维持有序性,支持
O(logN)
级别 范围查询、排名计算。 - 哈希表 提供
O(1)
快速访问,用于查找成员是否存在及其分数。
ZSet 可高效实现 排行榜、积分榜、点赞榜、搜索权重排序 等场景,支持 ZADD
、ZRANGE
、ZREVRANK
等操作。
# 答案解析
# 1. ZSet(Sorted Set)底层结构
ZSet = 跳表(SkipList)+ 哈希表(Hash Table)
- 跳表(SkipList)
- 维护 有序结构,支持 范围查询(ZRANGE),时间复杂度
O(logN)
。 - 采用 多级索引,加快查询效率,适用于大规模数据排序。
- 维护 有序结构,支持 范围查询(ZRANGE),时间复杂度
- 哈希表(Hash Table)
- 通过 Key → Score 映射,快速查询元素是否存在,
O(1)
复杂度。 - 适用于
ZSCORE
、ZINCRBY
操作。
- 通过 Key → Score 映射,快速查询元素是否存在,
📌 两者结合:跳表提供排序和排名,哈希表提供快速访问。
# 2. Redis ZSet 如何实现排行榜
ZSet 适用于 积分排行榜、点赞排行榜、搜索权重排序 等。
# (1)插入数据
ZADD leaderboard 100 "Alice"
ZADD leaderboard 200 "Bob"
ZADD leaderboard 150 "Charlie"
1
2
3
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
2
3
4
- 查询 Tom 需要 1 次跳跃,查询 Alice 需要 3 次跳跃。
# 4. ZSet vs. Set vs. List
结构 | 适用场景 | 排序 | 访问速度 |
---|---|---|---|
ZSet | 排行榜、搜索权重 | ✅ 有序 | O(logN) 查询 |
Set | 去重、共同关注 | ❌ 无序 | O(1) 查询 |
List | 消息队列、聊天记录 | ✅ 按插入顺序 | O(N) 查询 |
# 深入追问
- Redis 跳表 vs. 红黑树,为什么选择跳表?
- 如何优化百万级排行榜?(分片、缓存方案)
- ZSet 适合排行榜,但不适合什么场景?
- 如果要存储 1 亿条数据的实时排行榜,如何优化?
- 如何实现基于时间衰减的动态排行榜?
# 相关面试题
- Redis ZSet 如何存储大规模用户排名数据?
- ZREVRANK vs. ZRANK 的区别?
- 如何用 Redis ZSet 实现“最近热搜”榜?
- ZSet 操作如何进行高并发优化?
- ZSet 存在大 Key 时,如何拆分优化?
# 总结
- ZSet 采用 跳表+哈希表 结合,支持 O(logN) 排名计算,适用于排行榜、积分榜等场景。
- 跳表比红黑树更简单,插入/查询效率更高。
- Redis 提供
ZADD
、ZREVRANK
、ZINCRBY
等指令,可高效操作排名数据。 - 排行榜场景可结合缓存、定期清理、分片优化,提升性能。
- ZSet 适用于有序数据排名,但不适用于高频写入的场景(如实时日志)。