Skip to content

Redis Zset(有序集合)


一、是什么?

Zset(Sorted Set)是 Redis 的一种数据结构,它结合了 Set(集合)Hash(哈希表) 的特性:

  1. 元素唯一性:成员(member)不允许重复(类似 Set)。
  2. 有序性:每个成员关联一个分数(score),按分数升序排序(默认)。
  3. 高效操作:支持基于分数或字典序的范围查询、排名操作等。

数据结构示例(Mermaid 示意图)


二、解决什么问题

  1. 排序需求:普通 Set 无法按值排序,Zset 通过分数实现动态排序。
  2. 高效范围查询:快速获取 Top N 数据(如排行榜)、指定分数区间的成员。
  3. 去重 + 权重:在需要唯一性且按权重操作的场景(如优先级队列)替代数据库查询。

三、核心命令(常用操作)

命令作用示例
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

四、应用场景

  1. 实时排行榜(如游戏积分榜):
    java
    // 添加玩家分数
    jedis.zadd("game_rank", 100, "Player1");
    jedis.zadd("game_rank", 85, "Player2");
    
    // 获取Top 3
    Set<String> top3 = jedis.zrevrange("game_rank", 0, 2);
  2. 带权重的任务队列:按优先级处理任务(分数=优先级)。
  3. 限流系统:用分数存储时间戳,定期清理过期数据(如 ZREMRANGEBYSCORE)。
  4. 数据统计:如按分数区间统计用户分布(如成绩分段)。

五、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❌ 无序键值对查询,无排序能力

七、重要注意事项

  1. 分数范围:分数是双精度浮点数(64位),但避免使用极大/极小值。
  2. 相同分数:分数相同时,按成员字典序排序(lexicographical order)。
  3. 性能
    • 添加/删除:O(log N)(N 为成员数量)。
    • 范围查询:O(log N + M)(M 为返回结果数)。
  4. 内存优化:使用 ziplist 编码(小规模数据),超过阈值转为 skiplist(跳表)。

八、总结

Zset 是 Redis 中 唯一支持按权重排序的集合,适用于排行榜、优先级队列等场景。其核心优势是:

  1. 通过分数实现高效排序和范围查询。
  2. 保证成员唯一性避免重复数据。
    在 Java 中可通过 Jedis/Lettuce 操作 Zset,结合 ZRANGEZINCRBY 等命令满足动态排序需求。