前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis zset 的一些使用

Redis zset 的一些使用

作者头像
haoming1100
发布2019-03-13 15:49:14
18.2K0
发布2019-03-13 15:49:14
举报
文章被收录于专栏:步履前行步履前行步履前行

最近做排行信息的时候用到了 Redis 的 Sorted Set, 写篇文章来和大家分享一波。

Sorted Set (有序集合)
通常我们也称为 zset,指的是在 redis 中,通常以 zset add 等命令操作

zset 通常包含 3 个 关键字操作:

  • key (与我们 redis 通常操作的 key value 中的key 一致)
  • score (排序的分数,该分数是有序集合的关键,可以是双精度或者是整数)
  • member (指我们传入的 obj,与 key value 中的 value 一致)

下面我们来看具体的相关命令


ZADD
ZADD key score member [[score member] [score member] ...]
  • [[score member] [score member] ...] 在Redis2.4 之后可以添加多个个元素

添加一个或者多个元素到 指定的 key 中。 如果该 key 中已经有了相同的 member,则更新该 member 的 score 值,并重排序;如果 key 存在于 redis 中, 但不是 zset 类型,则返回错误。

示例

# 添加1个元素

redis> ZADD key_1 100 xiaoming
(integer) 1

# 添加多个元素

redis> ZADD key_1 100 xiaoming 20 xiaohong
(integer) 2

#查看元素 score值递增(从小到大)来排序。 如果需要 按score值递减(从大到小)来排列,使用ZREVRANGE命令。
WITHSCORES选项,来让成员和它的score值一并返回

redis> ZRANGE key_1 0 -1 WITHSCORES
1) "xiaohong"
2) "20"
3) "xiaoming"
4) "100"

可以从上面的例子看出 ZADD 命令还是很容易理解的


ZREM

    ZREM key member [member ...]

说完了添加,我们肯定要讲移除了, 与 ZADD 命令一样,也支持多个删除操作(当然也是在2.4版本之后)。这里有个要注意的点,在移除的过程中,如果 member 不存在,将被忽略。

key 存在但是不是 zset,同样会报错

示例

# 移除单个元素

redis> ZREM key_1 xiaohong
(integer) 1


# 移除多个元素

redis> ZREM key_1 xiaohong xiaoming
(integer) 2

# 移除不存在元素

redis> ZREM key_1 xiaolin
(integer) 0

ZCARD

    ZCARD key

返回 key 的成员个数。 key不存在时,返回0

# 添加一个 key 及其成员

127.0.0.1:6379> ZADD key_1 100 xiaoming
(integer) 1

# 查找 key 的成员个数

127.0.0.1:6379> ZCARD key_1
(integer) 1

# 添加 第二个成员

127.0.0.1:6379> ZADD key_1 20 xiaohong
(integer) 1

# 可以看到 key_1 的成员个数变成了 2 个

127.0.0.1:6379> ZCARD key_1
(integer) 2
 
# 查看不存在的 key

127.0.0.1:6379> ZCARD key_2
(integer) 0

ZCOUNT

    ZCOUNT key min max

返回指定 key 的 分数在 min 与 max 之间的 member 个数

# 分数在 50 到 100 之间的个数

127.0.0.1:6379> ZCOUNT key_1 50 100
(integer) 1

ZSCORE

    ZSCORE key member

返回指定 key 和 member 的 分数值

# 获取 key_1 的成员 xiaoming 的分数值

127.0.0.1:6379> ZSCORE key_1 xiaoming
"100"

ZINCRBY

    ZINCRBY key increment member

为指定 key 的 member 的分数值 加 increment,其中 increment 代表数值,increment 可以是 负数,代表减去。

如果 key 或者 member 不存在,代表 ZADD 操作

# 查看 key_1 的 成员 xiaoming  的分数

127.0.0.1:6379> ZSCORE key_1 xiaoming
"100"

# 给 key_1 的 成员 xiaoming 的分数 加上 100
127.0.0.1:6379> ZINCRBY key_1 100 xiaoming
"200"

# 查看 key_1 的 成员 xiaoming  的分数
127.0.0.1:6379> ZSCORE key_1 xiaoming
"200"

ZRANGE

    ZRANGE key start stop [WITHSCORES]

返回指定 key 的 指定下标的成员, start stop 代表下标区间。

返回的结果默认按照分数==从小到大==排列,如果需要 ==从大到==小排列,需要是用 ZREVRANGE 命令。

  • start 和 stop 都以 0 开始,比如,0 为第一个成员,1 为第二个成员。
  • 可以用 -1 表示最后一个成员, -2 表示倒数第二个成员
  • WITHSCORES 可以返回相关成员 及其分数
# 查看 第一个 和 第二个成员
127.0.0.1:6379> ZRANGE key_1 0 1
1) "xiaohong"
2) "xiaoming"

# 查看所有的成员
127.0.0.1:6379> ZRANGE key_1 0 -1
1) "xiaohong"
2) "xiaoming"

# 查看成员 以及分数

127.0.0.1:6379> ZRANGE key_1 0 -1 WITHSCORES
1) "xiaohong"
2) "20"
3) "xiaoming"
4) "200"

ZREVRANGE

    ZREVRANGE key start stop [WITHSCORES]

用法和 ZRANGE 相同,只是排序是按照 分数 从大到小

# 按照分数从大到小排列
127.0.0.1:6379> ZREVRANGE key_1 0 -1 WITHSCORES
1) "xiaoming"
2) "200"
3) "xiaohong"
4) "20"

ZRANGEBYSCORE

    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

返回指定分数的成员。分数在 min max 之间,返回的成员按照 分数 从小到大排列

  • LIMIT 指定返回结果的区间和 数量,与 sql 中的 limit 一样
# 查看分数在 0 到 200 之间的 成员
127.0.0.1:6379> ZRANGEBYSCORE key_1 0 200
1) "xiaohong"
2) "xiaoming"
  • min 和 max 可以带入 开区间和闭区间的概念
# 查看分数在 0 到 199 之间的成员
127.0.0.1:6379> ZRANGEBYSCORE key_1 0 (200
1) "xiaohong"

ZREVRANGEBYSCORE

    ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

与ZRANGEBYSCORE用法一样,只是返回的成员按照 分数从大到小排列

# 注意 分数要按照 max min 写,否则结果是空值
127.0.0.1:6379> ZREVRANGEBYSCORE key_1 200 0
1) "xiaoming"
2) "xiaohong

# 错误示例
127.0.0.1:6379> ZREVRANGEBYSCORE key_1 0 200
(empty list or set)

ZRANK

    ZRANK key member

返回指定key 的成员排名,按照分数 从小到大排列,其中==返回的排名是以 0 开始==

# 查看 key_1 的成员
127.0.0.1:6379> ZRANGE key_1 0 -1
1) "xiaohong"
2) "xiaoming"

# 查看xiaoming 的排名
127.0.0.1:6379> ZRANK key_1 xiaoming
(integer) 1

# 查看xiaohong 的排名
127.0.0.1:6379> ZRANK key_1 xiaohong
(integer) 0

ZREVRANK

    ZREVRANK key member

与 ZRANK 的用法相同,区别就是按照分数 从大到小排列

127.0.0.1:6379> ZRANGE key_1 0 -1
1) "xiaohong"
2) "xiaoming"

# 反转排序
127.0.0.1:6379> ZREVRANK key_1 xiaohong
(integer) 1

ZREMRANGEBYRANK

    ZREMRANGEBYRANK key start stop

移除指定 key 的指定排名介于 start 和 stop 之间的成员,同样排名以 0 开始。

# 查看排名
127.0.0.1:6379> ZRANGE key_1 0 -1
1) "xiaohong"
2) "xiaoming"

# 移除 排名 为0 的成员
127.0.0.1:6379> ZREMRANGEBYRANK key_1 0 0
(integer) 1

# 查看排名,已移除
127.0.0.1:6379> ZRANGE key_1 0 -1
1) "xiaoming"

ZREMRANGEBYSCORE

    ZREMRANGEBYSCORE key min max

移除指定key的 分数介于 min 和 max 之间的成员

# 查看成员
127.0.0.1:6379> ZRANGE key_1 0 -1 WITHSCORES
1) "xiaohong"
2) "20"
3) "xiaoming"
4) "200"

# 移除分数为 0 到 100 之间的成员
127.0.0.1:6379> ZREMRANGEBYSCORE key_1 0 100
(integer) 1

# 查看成员
127.0.0.1:6379> ZRANGE key_1 0 -1 WITHSCORES
1) "xiaoming"
2) "200"

ZINTERSTORE

    ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

上面的命令这么多,其实讲明了就是下面这几个

  • destination 给定的一个新的集合
  • numkeys 计算的几个集合
  • 之后的就是集合到的key了 举例
# 查看 key_1 的成员及其 分数
127.0.0.1:6379> ZRANGE key_1 0 -1 WITHSCORES
1) "xiaohong"
2) "50"
3) "xiaoming"
4) "200"

# 查看 key_2 的成员及其分数
127.0.0.1:6379> ZRANGE key_2 0 -1 WITHSCORES
1) "xiaohong"
2) "70"
3) "xiaoming"
4) "100"

# 把 key_1 和 key_2 根据 成员 把相关的 分数加起来到一个新的集合 sum_key
127.0.0.1:6379> ZINTERSTORE sum_key 2 key_1 key_2
(integer) 2
127.0.0.1:6379> ZRANGE sum_key 0 -1 WITHSCORES
1) "xiaohong"
2) "120"
3) "xiaoming"
4) "300"

ZUNIONSTORE

    ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

这个命令和上面的命令用法基本相同 只是有个算法因子的参数,比如 key_1 key_2 WEIGHTS 2 2 那么key_1 的分数和key_2 的分数 各自乘以 2

ZUNIONSTORE 用于计算给定的一个或多个有序集的==并集==。 ZINTERSTORE 则用于计算给定的一个或多个有序集的==交集==。

# 查看 key_2 的成员及其分数
127.0.0.1:6379> ZRANGE key_2 0 -1 WITHSCORES
1) "xiaohong"
2) "70"
3) "xiaoming"
4) "100"

# 查看 key_3 的成员及其分数
127.0.0.1:6379> ZRANGE key_3 0 -1 WITHSCORES
1) "xiaoli"
2) "80"
3) "xiaoxia"
4) "180"

# UNION key_2 key_3 没有写 乘法因子 默认是 1
127.0.0.1:6379> ZUNIONSTORE union0 2 key_2 key_3
(integer) 4
127.0.0.1:6379> ZRANGE union0 0 -1 WITHSCORES
1) "xiaohong"
2) "70"
3) "xiaoli"
4) "80"
5) "xiaoming"
6) "100"
7) "xiaoxia"
8) "180"

# UNION key_2 key_3 key_2 和 key_3 各自乘以2 
127.0.0.1:6379> ZUNIONSTORE union1 2 key_2 key_3 WEIGHTS 2 2
(integer) 4
127.0.0.1:6379> ZRANGE union1 0 -1 WITHSCORES
1) "xiaohong"
2) "140"
3) "xiaoli"
4) "160"
5) "xiaoming"
6) "200"
7) "xiaoxia"
8) "360"

下面则是 根据RedisTemplate 写的一个通用类,仅供参考

@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    public <T> Boolean setIfAbsent(String key, T value) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        return valueOperations.setIfAbsent(key, value);
    }

    public Boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    public <T> Boolean expireAt(T key, final Date date) {
        return redisTemplate.expireAt(key, date);
    }

    public void delete(final String key) {
        redisTemplate.delete(key);
    }

    public <T> void set(String redisKey, T obj, double score) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        //zset内部是按分数来排序的
        zSetOperations.add(redisKey, obj, score);
    }


    public <T> Double score(String redisKey, T obj) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.score(redisKey, obj);
    }

    /**
     * 移除key相关的成员
     *
     * @param redisKey
     * @param start
     * @param end
     * @param <T>
     * @return
     */
    public <T> Long removeRange(String redisKey, long start, long end) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.removeRange(redisKey, start, end);
    }

    public <T> Long remove(String redisKey, Object... values) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.remove(redisKey, values);
    }

    /**
     * 移除的是成员value
     *
     * @param redisKey
     * @param min
     * @param max
     * @param <T>
     * @return
     */
    public <T> Long removeRangeByScore(String redisKey, double min, double max) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.removeRangeByScore(redisKey, min, max);
    }

    public <T> Long zCard(String redisKey) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.zCard(redisKey);
    }

    public <T> Set range(String redisKey, long start, long end) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.range(redisKey, start, end);
    }

    /*
     * 按照【分数】排序对指定区间取值和分数
     */
    public <T> Set rangeByScoreWithScores(String score, double min, double max) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.rangeByScoreWithScores(score, min, max);
    }

    /**
     * 获取下标
     *
     * @param redisKey
     * @param v
     * @param <T>
     * @return
     */
    public <T> Long rank(String redisKey, Object v) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.rank(redisKey, v);
    }

    /**
     * 获取区间的个数
     *
     * @param redisKey
     * @param min
     * @param max
     * @param <T>
     * @return
     */
    public <T> Long count(String redisKey, double min, double max) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.count(redisKey, min, max);
    }

    public <T> Set rangeByLex(String redisKey, RedisZSetCommands.Range range) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.rangeByLex(redisKey, range);
    }

    public <T> Set rangeByScore(String key, double min, double max) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.rangeByScore(key, min, max);
    }

    public <T> Set rangeByScore(String key, double min, double max, long offset, long count) {
        ZSetOperations<String, T> zSetOperations = this.redisTemplate.opsForZSet();
        return zSetOperations.rangeByScore(key, min, max, offset, count);
    }

}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-02-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Sorted Set (有序集合)
  • ZADD
  • ZREM
  • ZCARD
  • ZCOUNT
  • ZSCORE
  • ZINCRBY
  • ZRANGE
  • ZREVRANGE
  • ZRANGEBYSCORE
  • ZREVRANGEBYSCORE
  • ZRANK
  • ZREVRANK
  • ZREMRANGEBYRANK
  • ZREMRANGEBYSCORE
  • ZINTERSTORE
  • ZUNIONSTORE
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档