Redis Zset(有序集合)
一、是什么?
Zset(Sorted Set)是 Redis 的一种数据结构,它结合了 Set(集合) 和 Hash(哈希表) 的特性:
- 元素唯一性:成员(member)不允许重复(类似 Set)。
- 有序性:每个成员关联一个分数(score),按分数升序排序(默认)。
- 高效操作:支持基于分数或字典序的范围查询、排名操作等。
数据结构示例(Mermaid 示意图):
二、解决什么问题
- 排序需求:普通 Set 无法按值排序,Zset 通过分数实现动态排序。
- 高效范围查询:快速获取 Top N 数据(如排行榜)、指定分数区间的成员。
- 去重 + 权重:在需要唯一性且按权重操作的场景(如优先级队列)替代数据库查询。
三、核心命令(常用操作)
命令 | 作用 | 示例 |
---|---|---|
ZADD key score member | 添加成员 | ZADD rank 90 Alice |
ZRANGE key start stop | 按索引升序查询成员 | ZRANGE rank 0 -1 |
ZREVRANGE | 按索引降序查询成员 | ZREVRANGE rank 0 2 |
ZRANGEBYSCORE | 按分数区间查询 | ZRANGEBYSCORE rank 80 95 |
ZRANK key member | 获取成员升序排名 | ZRANK rank Alice |
ZREM key member | 删除成员 | ZREM rank Bob |
ZINCRBY key increment member | 增加成员分数 | ZINCRBY rank 5 Alice |
四、应用场景
- 实时排行榜(如游戏积分榜):java
// 添加玩家分数 jedis.zadd("game_rank", 100, "Player1"); jedis.zadd("game_rank", 85, "Player2"); // 获取Top 3 Set<String> top3 = jedis.zrevrange("game_rank", 0, 2);
- 带权重的任务队列:按优先级处理任务(分数=优先级)。
- 限流系统:用分数存储时间戳,定期清理过期数据(如
ZREMRANGEBYSCORE
)。 - 数据统计:如按分数区间统计用户分布(如成绩分段)。
五、Java 示例(Jedis 客户端)
java
import redis.clients.jedis.Jedis;
import java.util.Set;
public class ZsetExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
// 添加成员
jedis.zadd("students", 90, "Alice");
jedis.zadd("students", 85, "Bob");
jedis.zadd("students", 95, "Charlie");
// 获取分数升序Top 2
Set<String> topStudents = jedis.zrange("students", 0, 1);
System.out.println("Top 2: " + topStudents); // [Bob, Alice]
// 查询分数在[88, 96]的成员
Set<String> range = jedis.zrangeByScore("students", 88, 96);
System.out.println("Score 88~96: " + range); // [Alice, Charlie]
// 删除成员
jedis.zrem("students", "Bob");
jedis.close();
}
}
六、与类似结构的区别
结构 | 唯一性 | 有序性 | 查询能力 |
---|---|---|---|
Zset | ✅ | 按分数排序 | 范围查询、排名、分数 |
Set | ✅ | ❌ 无序 | 仅支持成员存在性检查 |
List | ❌ | 按插入顺序排序 | 通过索引查询,不支持排序 |
Hash | ✅ | ❌ 无序 | 键值对查询,无排序能力 |
七、重要注意事项
- 分数范围:分数是双精度浮点数(64位),但避免使用极大/极小值。
- 相同分数:分数相同时,按成员字典序排序(lexicographical order)。
- 性能:
- 添加/删除:
O(log N)
(N 为成员数量)。 - 范围查询:
O(log N + M)
(M 为返回结果数)。
- 添加/删除:
- 内存优化:使用
ziplist
编码(小规模数据),超过阈值转为skiplist
(跳表)。
八、总结
Zset 是 Redis 中 唯一支持按权重排序的集合,适用于排行榜、优先级队列等场景。其核心优势是:
- 通过分数实现高效排序和范围查询。
- 保证成员唯一性避免重复数据。
在 Java 中可通过 Jedis/Lettuce 操作 Zset,结合ZRANGE
、ZINCRBY
等命令满足动态排序需求。