Redis:ZSet数据结构使用

// zset存

// 初始化key,value为userId,分数为0
redisTemplate.opsForZSet().add(key, userId, 0 ) ;
// 设置过期时间
redisTemplate.expire(key, Duration.ofDays(2));
// 给key,value为userId,原子增score的分数
redisTemplate.opsForZSet().incrementScore(key, userId, score);    


// zset取

// 查询top5的从小到大 zrange key 0 4
Set<String> set = stringRedisTemplate.opsForZSet().range(key, 0, 4);
if(set==null || set.isEmpty()){
    throw new Exception("key中暂无数据");
}

// userId移除
stringRedisTemplate.opsForZSet().remove(key, userId);

// 滚动分页查询
// ZREVRANGEBYSCORE key Max Min LIMIT offset count
// Max:当前最大分数(第一次查询使用) | 上一次查询的最小分数 (除了第一次查询之外都使用)
// Min:0
// offset:0 (第一次查询使用) | 在上一次的结果中,与最小值一样的元素个数 (除了第一次查询之外都使用)
// count:分页大小 比如3
Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, max, offset, 3);
// 非空判断
if (typedTuples == null || typedTuples.isEmpty()) {
    return Result.ok();
}

// 解析数据:userId、minScore、offset
List<Long> ids = new ArrayList<>(typedTuples.size());
long minScore = 0; // 2
int os = 1; // 2
for (ZSetOperations.TypedTuple<String> tuple : typedTuples) { // 5 4 4 2 2
    // 4.1.获取userId
    ids.add(Long.valueOf(tuple.getValue()));
    // 4.2.获取分数
    long score = tuple.getScore().longValue();
    if (score == minScore) {
        os++;
    } else {
        minScore = score;
        os = 1;
    }
}
// 将minScore即为max和os即为offset返回给前端

<think>嗯,用户之前问了一个关于Java集合的问题,现在又问RedisZSET数据结构。我需要先回顾一下之前的对话,看看是否有联系。之前的回答解释了为什么修改Integer列表元素不生效,涉及到了不可变对象和集合操作的问题。现在用户转向Redis数据结构,可能是在学习不同的存储结构,或者在做项目时需要考虑数据存储方式。 首先,用户可能对Redis的基础有一定了解,但想深入理解ZSET。需要先介绍ZSET是什么,它的特点,比如有序、唯一成员、分数排序等。然后要解释底层实现,比如跳跃表和哈希表的结合,这样用户能明白为什么ZSET高效。 接下来,用户可能需要知道ZSET的常用命令,比如ZADD、ZRANGE、ZREVRANGE等,这些是操作ZSET的基本命令。给出示例能帮助用户更好地理解如何使用。另外,应用场景也很重要,用户可能想知道在实际开发中哪里会用到ZSET,比如排行榜、延时队列、范围查询等,这部分需要结合实际例子说明。 还要注意用户可能的进阶问题,比如为什么选择跳跃表和哈希表,或者ZSET的时间复杂度,这样可以在解释时提前涵盖这些点。此外,用户可能对ZSET和其他数据结构的区别感兴趣,比如和SET的区别,或者和列表的区别,可以简要提及。 最后,确保语言通俗易懂,避免过多技术术语,但又要准确。可能需要检查是否有错误,比如ZSET是否真的使用两种数据结构,或者命令的正确写法。另外,用户之前的问题涉及到修改集合元素,这里可以提一下ZSET的更新操作是否直接,比如更新分数是否容易,这也是实际应用中的常见需求。 总结下来,回答的结构应该是先定义ZSET,然后底层结构,常用命令,应用场景,最后注意事项。这样用户能逐步深入了解,并且能应用到实际项目中。同时,要确保信息准确,示例正确,帮助用户形成清晰的理解。</think>Redis 的 **ZSET**(有序集合,Sorted Set)是一种结合了 **Set**(成员唯一)和 **Sorted**(按分数排序)特性的数据结构。它通过为每个成员分配一个 `score`(分数)来实现排序,是 Redis 中非常实用且高效的数据结构之一。 --- ### **核心特性** 1. **唯一成员,可重复分数** - 每个成员(`member`)唯一,但多个成员可以拥有相同的 `score`。 - 例如:`ZADD rank 90 "Alice" 90 "Bob"`,允许两人分数相同。 2. **按分数排序** - 默认按 `score` **升序**排列,支持范围查询(如获取排名前 N 的成员)。 - 可以通过 `ZREVRANGE` 实现降序排序。 3. **高性能操作** - 插入、删除、查询的时间复杂度为 **O(log N)**,基于底层**跳跃表(Skip List)**实现。 --- ### **底层实现** ZSET 内部使用两种结构组合实现: 1. **跳跃表(Skip List)** - 支持快速的范围查询(如 `ZRANGE`)和排序。 2. **哈希表(Hash Table)** - 以 `member` 为键,`score` 为,实现 **O(1)** 复杂度的单个成员查询(如 `ZSCORE`)。 这种组合兼顾了**范围操作的高效性**和**单成员查询的快速性**。 --- ### **常用命令** | 命令 | 作用 | 示例 | |------|------|------| | `ZADD` | 添加成员 | `ZADD key score member [score2 member2 ...]` | | `ZRANGE` | 按升序返回成员 | `ZRANGE key start stop [WITHSCORES]` | | `ZREVRANGE` | 按降序返回成员 | `ZREVRANGE key start stop [WITHSCORES]` | | `ZRANK` | 获取成员升序排名 | `ZRANK key member` | | `ZSCORE` | 获取成员分数 | `ZSCORE key member` | | `ZREM` | 删除成员 | `ZREM key member` | | `ZCOUNT` | 统计分数区间内的成员数 | `ZCOUNT key min_score max_score` | --- ### **典型应用场景** 1. **排行榜** - 例如游戏积分排名,通过 `ZREVRANGE` 直接获取 Top N 玩家。 2. **延时队列** - 将任务到期时间作为 `score`,用 `ZRANGEBYSCORE` 轮询到期任务。 3. **范围查询** - 如按时间范围筛选数据(将时间戳作为 `score`)。 4. **权重调度** - 用 `score` 表示优先级,按权重顺序处理任务。 --- ### **示例:实现排行榜** ```bash # 添加玩家分数 ZADD rank 95 "Alice" 88 "Bob" 100 "Charlie" # 获取前2名(降序) ZREVRANGE rank 0 1 WITHSCORES # 输出:1) "Charlie" 2) "100" 3) "Alice" 4) "95" # 更新 Alice 的分数(直接覆盖) ZADD rank 99 "Alice" # 查询 Alice 的排名(升序排名从0开始) ZRANK rank "Alice" # 返回1(Bob=88, Alice=99, Charlie=100) ``` --- ### **注意事项** 1. **分数范围** - `score` 是双精度浮点数,但 Redis 实际存储为 64 位整数(可能导致精度丢失)。 2. **性能** - 超大 ZSET(如百万级成员)的批量操作可能较慢,需合理分片。 3. **内存优化** - 若仅需排序,可用 `ZSET`;若需要更复杂操作,可能需结合其他数据结构(如 Hash)。 ZSET 凭借其排序能力和高效操作,成为 Redis 中解决**有序且唯一**场景的利器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员无羡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值