



























ZSet(Sorted Set)= 有序集合
元素 不重复(唯一 key),但可以有相同的分值(score)。
元素按照 score 从小到大排序。
支持按 score 范围 / 排名区间 查询,非常高效。
语法示例:
ZSet 是 Redis 内部比较复杂的结构之一 —— 实际上是由 两种数据结构组合 实现的:
| 组件 | 作用 | 复杂度 |
|---|---|---|
| dict(哈希表) | 存放成员到分值的映射(member → score) | O(1) |
| skiplist(跳表) | 存放分值到成员的排序关系(score → member) | O(logN) |
Redis 会同时维护这两个结构以保证:
通过成员快速查找分值(dict)
通过分值范围快速排序和遍历(skiplist)
跳表是一种多层链表结构,通过“多级索引”加速查找,类似于二分查找。
时间复杂度:O(logN)
插入、删除、范围扫描都非常高效。
跳表示意:
| 操作 | 命令 | 时间复杂度 | 说明 |
|---|---|---|---|
| 插入/更新 | ZADD key score member |
O(logN) | 若成员存在则更新分值 |
| 删除 | ZREM key member |
O(logN) | 同时从 dict 与 skiplist 删除 |
| 按分值范围查 | ZRANGEBYSCORE key min max |
O(logN + M) | M 为返回数量 |
| 按排名范围查 | ZRANGE key start stop |
O(logN + M) | 支持逆序 |
| 查成员分值 | ZSCORE key member |
O(1) | 从 dict 查 |
| 查排名 | ZRANK key member |
O(logN) | 从 skiplist 查 |
| 增加分值 | ZINCRBY key increment member |
O(logN) | 自动更新位置 |
| 删除区间 | ZREMRANGEBYSCORE key min max |
O(logN + M) | 范围删除 |
| 集合并集 | ZUNIONSTORE / ZINTERSTORE |
O(N logN) | 分值加权合并 |
场景: 游戏积分榜、电商热度榜、内容点赞排行等
设计:
优势:
实时更新分值。
可快速取前 N 名、后 N 名、某区间段。
场景: 定时任务、重试队列、延迟通知等
思路:
score = 任务执行时间戳
定时轮询当前时间 ≤ score 的任务
优点:
不依赖外部消息系统
可控制延迟精度(秒级)
场景: 内容推荐、最热文章、热门搜索词
思路:
每次访问调用 ZINCRBY 累加热度
定时取前 N 名显示
场景: 风控任务、风控规则优先级处理
score = 权重(越高优先级越高)
用 ZPOPMAX 每次取最高优先级任务处理
用户行为打分、信用评分、综合指标
可存历史分数,定期做 decay(衰减)
| 优势 | 说明 |
|---|---|
| 有序、可快速范围查询 | 按分值排序,支持分页、区间 |
| 插入、删除、查找效率高 | 跳表 O(logN) |
| 支持原子操作 | 不需要事务就能安全并发修改 |
| 数据量大也能稳定性能 | 比 list 链表结构高效 |
| 缺点 | 说明 |
|---|---|
| 内存占用较高 | 维护 skiplist + dict |
| 无法去重按值排序(只能按 score) | 需自行定义 score 规则 |
| 不支持按 value 排序 | 必须以 score 为序 |
| 类型 | 是否排序 | 是否唯一 | 查询复杂度 | 典型场景 |
|---|---|---|---|---|
| String | 否 | 是(键唯一) | O(1) | KV 存储 |
| List | 按插入顺序 | 可重复 | O(N) | 消息队列 |
| Set | 无序 | 唯一 | O(1) | 去重集合 |
| ZSet | ✅ 有序 | ✅ 唯一 | O(logN) | 排行榜、延迟队列、TopN |
① ZSet 底层实现是什么?
跳表(skiplist)+ 哈希表(dict)。
跳表用于按分值排序,哈希表用于 O(1) 查找分值。
② 插入和查询的复杂度是多少?
O(logN) 插入,O(1) 查找,O(logN+M) 范围查。
③ 为什么不用红黑树?
Redis 选择跳表主要因为:
插入/删除更简单;
实现更直观;
更适合范围遍历;
占用内存少,性能稳定。
④ 怎么实现延迟队列?
score 存未来执行时间戳,定期
ZRANGEBYSCORE拉取可执行任务。
⑤ 怎么实现排行榜 TopN?
score 存积分,
ZREVRANGE取前 N 名。
⑥ 如果有 1 亿个用户,取前 100 名怎么优化?
用 ZSet 存局部排行榜 + 分片聚合;
或者采用 Top-K 算法(如 Min-Heap)+ 定期同步 Redis。
⚙️ pipeline 批量写入:避免多次网络往返。
🧩 热榜分层缓存:TopN 存本地内存,底层数据异步更新。
🔄 分布式排行榜:按业务分片多个 ZSet,合并时在应用层聚合。
⏳ 数据过期策略:结合 TTL 或周期性清理。
💾 持久化:RDB/AOF 支持 ZSet,重启不丢失。
| 模块 | 内容 |
|---|---|
| 底层结构 | dict + skiplist |
| 复杂度 | 插入/删除 O(logN),查找 O(1) |
| 常用命令 | ZADD, ZRANGE, ZREVRANK, ZINCRBY, ZREMRANGEBYSCORE |
| 典型场景 | 排行榜、延迟队列、TopN、权重队列 |
| 优势 | 有序、高性能、原子操作 |
| 缺点 | 内存占用较高,按 value 排序不支持 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。