Redis | Redis 有序集合相关命令

时间:2022-07-24
本文章向大家介绍Redis | Redis 有序集合相关命令,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Redis 支持多种数据结构,比如 字符串、列表、集合、有序集合 和 哈希 等数据结构。本次我整理了关于 有序集合 相关的命令,也就是关于 Sorted Sets 相关的命令,如下图。

上图中用红色圈中的部分,就是关于 有序集合 相关的命令。如果想要在 Redis 中查看相关的命令可以使用 help 命令来进行查看,命令如下。

127.0.0.1:6379> help @sorted_set

在按下回车后,可以看到 Sorted Sets 相关命令的说明,如下图。

图中就是部分关于 Sorted Sets 相关的部分命令。对于 Sorted Sets 有另外一个名称 —— zsetszset

常用 Sorted Sets 相关命令

Sorted Sets 数据类型是 Key 对应的 Value 的类型,在 Redis 中所有的 Key 都是字符串类型,所谓的数据类型表示的是 Value 的类型。在 Sorted Sets 中的 Value 是一个有序集合,集合是有序的(上篇文章的 Sets 是无序的),且是不可以重复的,有序集合包含两部分,分别是成员(member)和分数(score)两部分。

为了大家能够直接复制命令进行测试,下面我就不截图了。

1、zadd

该命令的作用是:添加一个或者多个带分数的成员到集合里,命令格式如下:

zadd key [NX|XX] [CH] [INCR] score member [score member ...]

例子如下:

127.0.0.1:6379> zadd language 100 java 200 c++ 50 python 150 ruby
(integer) 4

在命令中,language 是 key其中 java、c++、 python 和 ruby 是 member,也就是成员它们前面的数值是 score,也就是分数。从返回值可以看出,zadd 命令增加了 4 个元素。

我们来查看一下用 zadd 添加的元素:

127.0.0.1:6379> zrange language 0 -1 withscores
1) "python"
2) "50"
3) "java"
4) "100"
5) "ruby"
6) "150"
7) "c++"
8) "200"

参数 NX 和 XX 的说明

nx:只添加新成员

127.0.0.1:6379> zadd language nx 200 java 130 php 180 c++
(integer) 1

127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "50"
 3) "java"
 4) "100"
 5) "php"
 6) "130"
 7) "ruby"
 8) "150"
 9) "c++"
10) "200"

可以看到 java 和 c++ 的分数都没有改变,php 加入了 zset。

xx:更新已经存在的成员

127.0.0.1:6379> zadd language xx 200 java 180 c++ 30 shell
(integer) 0
127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "50"
 3) "php"
 4) "130"
 5) "ruby"
 6) "150"
 7) "c++"
 8) "180"
 9) "java"
10) "200"

可以看到 java 和 c++ 的分数发生了改变,而 shell 并没有加入 zset 当中。

ch:返回值为发生变化的成员总数

前面我们看到 zadd 的返回值是添加成员的个数,使用 ch 参数后,zadd 的返回值为发生变化的成员的个数

127.0.0.1:6379> zadd language ch 210 java
(integer) 1
127.0.0.1:6379> zadd language 220 java
(integer) 0

对比上面两条命令的返回值,使用了 ch 参数后,返回值为 1,说明有一个成员发生了变化;没有使用 ch 参数,返回值为 0,表示添加了 0 个成员。

incr:zadd 指令不再是设置,而是增加

前面 python 的值为 50,我们使用 incr 参数对 python 的分数进行增加,命令如下:

127.0.0.1:6379> zadd language incr 50 python
"100"
127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "100"
 3) "php"
 4) "130"
 5) "ruby"
 6) "150"
 7) "c++"
 8) "180"
 9) "java"
10) "220"

可以看到,python 的分数为 100,不增加 incr 参数的情况:

127.0.0.1:6379> zadd language 50 python
(integer) 0
127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "50"
 3) "php"
 4) "130"
 5) "ruby"
 6) "150"
 7) "c++"
 8) "180"
 9) "java"
10) "220"

可以看到,没有 incr 参数时,zadd 还具有设置分数的作用

2、zcard

该命令的作用是:获取指定 key 中的成员数量。

127.0.0.1:6379> zcard language
(integer) 5
127.0.0.1:6379> zrange language 0 -1
1) "python"
2) "php"
3) "ruby"
4) "c++"
5) "java"

3、zcount

该命令的作用是:获取指定 key 下分数范围内的成员的数量

127.0.0.1:6379> zcount language 150 180
(integer) 2
127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "50"
 3) "php"
 4) "130"
 5) "ruby"
 6) "150"
 7) "c++"
 8) "180"
 9) "java"
10) "220"

从上面的命令可以看出,分数在 150 到 180 之间的成员有两个。

4、zincrby

该命令的作用是:给 key 中的成员增加分数

127.0.0.1:6379> zincrby language 10 python
"60"
127.0.0.1:6379> zrange language 0 -1 withscores
 1) "python"
 2) "60"
 3) "php"
 4) "130"
 5) "ruby"
 6) "150"
 7) "c++"
 8) "180"
 9) "java"
10) "220"

5、zpopmax

该命令的作用是:返回指定 key 的分数最大的 N 个成员,并将返回的成员从 key 中删除

127.0.0.1:6379> zpopmax language 1
1) "java"
2) "220"

在上面的命令中,language 后跟随的数值就是要获取的分数最大的 N 个成员

127.0.0.1:6379> zrange language 0 -1
1) "python"
2) "php"
3) "ruby"
4) "c++"

6、zpopmin

该命令的作用是:返回指定 key 的分数最小的 N 个成员,并将成员从 key 中删除

127.0.0.1:6379> zpopmin language 1
1) "python"
2) "60"
127.0.0.1:6379> zrange language 0 -1 withscores
1) "php"
2) "130"
3) "ruby"
4) "150"
5) "c++"
6) "180"

7、zrange

该命令的作用是:返回指定 key 中索引范围内的成员,命令格式如下

zrange key start stop [WITHSCORES]

这个命令是我们使用最多的命令,在上面的例子中已经反复使用过了。这里具体介绍一下。

127.0.0.1:6379> zrange language 0 -1
1) "php"
2) "ruby"
3) "c++"

命令格式中的,0 和 -1 表示查看 zset 中从开始位置到结束位置的所有成员,zset 的索引从 0 开始,-1 表示最后一个索引的位置,同理,第二个元素的索引值为 1,倒数第二个索引可以使用 -2 表示。

127.0.0.1:6379> zrange language -2 -1
1) "ruby"
2) "c++"
127.0.0.1:6379> zrange language 0 -2
1) "php"
2) "ruby"

命令格式中的 withscores 表示查看各个成员对应的分数,例子如下:

127.0.0.1:6379> zrange language 0 -1 withscores
1) "php"
2) "130"
3) "ruby"
4) "150"
5) "c++"
6) "180"

8、zrevrange

该命令的作用是:返回指定 key 中索引范围内的成员,顺序由高到底,命令格式如下:

zrevrange key start stop [WITHSCORES]

该命令与 zrange 类似,zrange 是按照分数由低到高的排序,而 zrevrange 则是由高到低进行排序,例子如下:

127.0.0.1:6379> zrevrange language 0 -1 withscores
1) "c++"
2) "180"
3) "ruby"
4) "150"
5) "php"
6) "130"

9、zrangebylex

该命令的作用是:按照字典顺序进行排序后获取指定区间的成员,且可以进行分页

127.0.0.1:6379> zadd score 0 aa 0 bb 0 cc 0 dd 0 ee 0 ff
(integer) 6

注意:使用 zrangebylex 要求所有成员的分数相同,因此上面的命令我们先添加一些要进行测试的成员和分数。

其命令格式如下:

ZRANGEBYLEX key min max [LIMIT offset count]

先来查看一下按照字典序进行排序的成员,命令如下:

127.0.0.1:6379> zrangebylex score - +
1) "aa"
2) "bb"
3) "cc"
4) "dd"
5) "ee"
6) "ff"

其中 - 号表示最小值+ 号表示最大值

127.0.0.1:6379> zrangebylex score [a [d
1) "aa"
2) "bb"
3) "cc"

可以看到,我们查看了左侧为以字母 a 开头的闭区间,和右侧为以字母 d 开头的开区间的成员列表在 min 和 max 进行匹配时,需要以 [ 或 ( 开头。网上资料中描述,[ 表示闭区间,( 开区间,但是经我测试发现,无论使用 [ 还是 ( ,最后的结果范围都是 左闭右开。(如果我测试的有误,也请大家指出,以便我进行改正,在此表示感谢!)

127.0.0.1:6379> zrangebylex score - (c
1) "aa"
2) "bb"

127.0.0.1:6379> zrangebylex score (a (c
1) "aa"
2) "bb"

从上面可以看出,使用 ( 同样时 左闭右开。

接着再看看 limit 的用法,limit 后面根两个参数,分别时 offset 和 count,也就是起始的偏移和数量,这两个参数类似 MySQL 的 limit 的用法。

127.0.0.1:6379> zrangebylex score - + limit 0 3
1) "aa"
2) "bb"
3) "cc"

127.0.0.1:6379> zrangebylex score - + limit 3 3
1) "dd"
2) "ee"
3) "ff"

10、zrevrangebylex

该命令的作用是:用法和 zrangebylex 类似,只是顺序是反的,命令格式如下:

zrevrangebylex key max min [LIMIT offset count]

zrevrangebylex 命令在 key 的后面先给出 max,再给出 min,这个顺序正好与 zrangebylex 的顺序相反,这里就不再演示了。

11、zlexcount

该命令的作用是:返回成员之间的数量,命令格式如下:

zlexcount key min max

该命令的格式与 zrangebylex 的格式类似,只是不返回具体的成员区间,而是成员区间的个数,例子如下:

127.0.0.1:6379> zlexcount score - +
(integer) 6
127.0.0.1:6379> zlexcount score (a (c
(integer) 2

12、zrangebyscore

该命令的作用是:按照分数进行排序并获取成员,命令格式如下:

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

查看所有的成员

127.0.0.1:6379> zrangebyscore language -inf +inf
1) "php"
2) "ruby"
3) "c++"

其中,-inf 和 +inf 分别代表负无穷大和正无穷大

127.0.0.1:6379> zrangebyscore language 100 150 withscores
1) "php"
2) "130"
3) "ruby"
4) "150"

查看带分数的分数区间再 100 到 150 之间的成员

127.0.0.1:6379> zrangebyscore language (130 (160 withscores
1) "ruby"
2) "150"

查看分数在 130 到 160 之间的开区间的成员,zrangebyscore 不能使用 [ 开头

13、zrevrangebyscore

该命令的作用是:该命令的排序与 zrangebyscore 的顺序相反,该命令的格式如下:

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

该命令就不进行演示

14、zrank

该命令的作用是:按照分数由低到高的顺序查看成员的排名

127.0.0.1:6379> zrank language php
(integer) 0
127.0.0.1:6379> zrank language c++
(integer) 2
127.0.0.1:6379> zrank language ruby
(integer) 1

15、zrevrank

该命令的作用是:按照分数由高到低的顺序查看成员的排名

127.0.0.1:6379> zrevrank language php
(integer) 2
127.0.0.1:6379> zrevrank language ruby
(integer) 1
127.0.0.1:6379> zrevrank language c++
(integer) 0

16、zrem

该命令的作用是:删除 zset 中的一个或多个成员,当成员为空时,删除该 key

127.0.0.1:6379> zrem language c++ php ruby
(integer) 3
127.0.0.1:6379> zrange language 0 -1
(empty list or set)
127.0.0.1:6379> keys *
1) "score"
2) "key"
3) "lang"

17、zremrangebyrank

该命令的作用是:按照排名进行删除成员,命令格式如下:

ZREMRANGEBYRANK key start stop

删除排名 0 和 1 的两个成员

127.0.0.1:6379> zadd language 50 c++ 100 java 150 asm 200 php 251 ruby 300 python
(integer) 6
127.0.0.1:6379> zremrangebyrank language 0 1
(integer) 2
127.0.0.1:6379> zrange language 0 -1
1) "asm"
2) "php"
3) "ruby"
4) "python"

18、zremrangebyscore

该命令的作用是:按照分数进行删除成员,命令格式如下:

ZREMRANGEBYSCORE key min max

删除分数再 201 到 260 之间的成员

127.0.0.1:6379> zremrangebyscore language 201 260
(integer) 1
127.0.0.1:6379> zrange language 0 -1
1) "asm"
2) "php"
3) "python"

ruby 成员被删除了

19、zremrangebylex

该命令的作用是:按照字典顺序进行删除成员,命令格式如下:

ZREMRANGEBYLEX key min max

删除字母 o 到 q 区间的成员

127.0.0.1:6379> zremrangebylex language [o [q
(integer) 2
127.0.0.1:6379> zrange language 0 -1
1) "asm"

可以看到,php 和 python 被删除了

20、zscore

该命令的作用是:获取指定成员的分数

127.0.0.1:6379> zscore language php
"130"
127.0.0.1:6379> zscore language c++
"180"
127.0.0.1:6379> zscore language c
(nil)
127.0.0.1:6379> zscore language ruby
"150"

21、zinterstore

该命令的作用是:将两个或多个 zset 求交集,命令格式如下:

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

求 k1 和 k2 的交集 k3,观察 k3 中成员的分数

127.0.0.1:6379> zadd k1 100 aa 200 bb 300 cc
(integer) 3
127.0.0.1:6379> zadd k2 100 aa 200 cc 300 dd
(integer) 3
127.0.0.1:6379> zinterstore k3 2 k1 k2 
(integer) 2
127.0.0.1:6379> zrange k3 0 -1
1) "aa"
2) "cc"
127.0.0.1:6379> zrange k3 0 -1 withscores
1) "aa"
2) "200"
3) "cc"
4) "500"

求 k1 和 k2 的交集 k4,观察 k4 中成员的分数,这次使用参数 weights,该参数表示对应集合的权重

127.0.0.1:6379> zinterstore k4 2 k1 k2 weights 2 3
(integer) 2
127.0.0.1:6379> zrange k4 0 -1
1) "aa"
2) "cc"
127.0.0.1:6379> zrange k4 0 -1 withscores
1) "aa"
2) "500"
3) "cc"
4) "1200"

weights 后面跟着 2 和 3,表示 k1 的分数权重是 2 倍,k2 的分数的权重是 3 倍。

k4(aa) = k1(aa) * 2 + k2(aa) * 3 = 100 * 2 + 100 * 3 = 500

最后一个参数 aggregate 表示交集的聚合方式:

相加的聚合方式:sum

127.0.0.1:6379> zinterstore k5 2 k1 k2 aggregate sum
(integer) 2
127.0.0.1:6379> zrange k5 0 -1 withscores
1) "aa"
2) "200"
3) "cc"
4) "500"

默认就是 k1 和 k2 相同成员的分数相加的形式

最小分数的聚合方式:min

127.0.0.1:6379> zinterstore k6 2 k1 k2 aggregate min
(integer) 2
127.0.0.1:6379> zrange k6 0 -1 withscores
1) "aa"
2) "100"
3) "cc"
4) "200"

k1 和 k2 的 aa 是相等的,因此 k6 的 aa 仍然是 100,而 k1 和 k2 的 cc 是不相等的,取了它们中较小的那个

最大分数的聚合方式:max

127.0.0.1:6379> zinterstore k7 2 k1 k2 aggregate max
(integer) 2
127.0.0.1:6379> zrange k7 0 -1 withscores
1) "aa"
2) "100"
3) "cc"
4) "300"

k1 和 k2 的 aa 是相等的,因此 k7 的 aa 仍然是 100,而 k1 和 k2 的 cc 是不相等的,取了它们中较大的那个

22、zunionstore

该命令的作用是:将两个或多个 zset 求并集,命令格式如下:

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

该命令的使用方式与 zinterstore 的方式相同,只是最后计算的是并集不是交集,这里不再进行演示。

总结

Redis 的有序集合类型提供的命令还是比较多的,它不但可以当作一个集合来用,它还具备 排名排序分页求交集求并集 的功能,当然, 还可以在一些特定的应用场景中轻松的完成功能的开发。

待 Redis 常用的几种基本数据类型总结完成后,我会再逐步的整理 Redis 这几种基本数据类型的各种应用场景,希望大家可以喜欢。

这部分整理花了两个晚上完成的,其实累计也就 2 个小时左右,由于时间比较仓促,可能有些命令描述的不是特别清楚或者准确,但是命令都是我逐个敲出来的,按照命令来进行学习,基本应该是没有问题的。当然了,有问题也可以指出来,我进行改正。