各位大佬晚上好,今天我们来学习下Redis的有序集合Zset(sorted set)。Zset和Set一样也是 string 类型元素的集合,且不允许重复的成员。其特性跟Set类似,也是通过哈希表实现的,所以添加、删除、查找都非常高效,复杂度都是 O(1)。

不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。正是因为这一特性,所以Zset很适合用于统计排行榜这一场景。

Zset的成员是唯一的,但其分数(score)是可以重复的。

简单的了解Zset后,接下来我们看看其常用的一些命令:

1、ZADD key [NX|XX] [CH] [INCR] score member [score member ...]:用于将一个或多个成员元素及其分数值加入到有序集当中。这里我们先讲下这些参数: NX、XX、CH、INCR。

  • NX:不更新存在的成员。只添加新成员;
  • XX:仅仅更新存在的成员,不添加新成员;
  • CH:修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内;
  • INCR:当ZADD指定这个选项时,成员的操作就等同于ZINCRBY命令,对成员的分数进行递增操作。

接下来我们使用ZADD命令添加一个key:

127.0.0.1:6379> ZADD key1 80 test1 90 test2
(integer) 2
127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "test1"
2) "80"
3) "test2"
4) "90"

接下来我们使用NX参数来操作下key1,我们使用ZRANGE命令发现test1的score并没有改变。

127.0.0.1:6379> ZADD key1 NX 70 test1 60 test3
(integer) 1
127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "test3"
2) "60"
3) "test1"
4) "80"
5) "test2"
6) "90"

其他的参数各位大佬们可以自己操作下,这里就不做演示了。

2、ZCARD key:用于计算获取有序集合的成员数量。

127.0.0.1:6379> ZCARD key1
(integer) 3

3、ZRANGE key start stop [WITHSCORES]:通过索引区间按分数值递增(从小到大)来排序,返回有序集合指定区间内的成员。WITHSCORES为可选参数,带该参数时会返回成员的score。

注意:具有相同分数值的成员按字典序来排列。

127.0.0.1:6379> ZRANGE key1 0 -1
1) "test3"
2) "test1"
3) "test2"
127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "test3"
2) "60"
3) "test1"
4) "80"
5) "test2"
6) "90"

4、ZCOUNT key min max:计算在有序集合中指定区间分数的成员数量。

127.0.0.1:6379> ZCOUNT key1 80 100
(integer) 2

5、ZINCRBY key increment member:对指定成员的分数加上增量 increment。

当成员不存在时,新增加一个成员,其分数(score)即为increment。

127.0.0.1:6379> ZRANGE key1 0 -1
(empty list or set)
127.0.0.1:6379> ZINCRBY key1 30 test1
"30"
127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "test1"
2) "30"
127.0.0.1:6379> ZINCRBY key1 50 test1
"80"
127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "test1"
2) "80"

 6、ZLEXCOUNT key min max:计算指定字典区间内成员数量。

min和max两个参数,需要使用符号"("和"[":

  • (min 表示返回的结果中不包含 min 值
  • (max 表示返回的结果中不包含 max 值
  • [min 表示返回的结果中包含 min 值
  • [max 表示返回的结果中包含 max 值
  • 可以使用-和+来替代[min和[max,-表示最小成员,+表示最大成员。
127.0.0.1:6379> ZADD myzset 0 a 1 b 2 c 3 d
(integer) 4
127.0.0.1:6379> ZADD myzset 4 e 5 f 6 g
(integer) 3
127.0.0.1:6379> ZLEXCOUNT myzset - +
(integer) 7
127.0.0.1:6379> ZLEXCOUNT myzset (a (f
(integer) 4
127.0.0.1:6379> ZLEXCOUNT myzset [a [f
(integer) 6

7、ZRANGEBYLEX key min max [LIMIT offset count]:通过字典区间返回有序集合的成员。

这个命令跟ZLEXCOUNT命令类似,区别是一个是返回成员,一个是返回数量。

可选择的3个参数:

  • LIMIT:表示是否分页,如果指令中包含了LIMIT,offset、count必须输入
  • offset:起始位置
  • count:结果数量
127.0.0.1:6379> ZRANGEBYLEX myzset - +
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
7) "g"
127.0.0.1:6379> ZRANGEBYLEX myzset (a (f
1) "b"
2) "c"
3) "d"
4) "e"
127.0.0.1:6379> ZRANGEBYLEX myzset [a [f
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379> ZRANGEBYLEX myzset - + LIMIT 0 3
1) "a"
2) "b"
3) "c"

8、ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]:通过分数返回指定区间内的成员。

  • 这里的min和max跟前面有所不同,查询整个有序数组的最小值和最大值时可分别用-inf和+inf表示
  • 最大或最小值前使用“(”时,不包括当前的分数,比如min使用(10,表示大于10的score,不使用括号时则包括当前分数即为大于等于10
  • LIMIT、offset、count,这三个参数跟前面一样是用来分页相关的

查看数组的所有成员,我们使用-inf和+inf:

127.0.0.1:6379> ZADD myzset 10 a 20 b 30 c 40 d 50 e 60 f
(integer) 6
127.0.0.1:6379> ZRANGEBYSCORE myzset -inf +inf
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"

显示score大于10到小于等于40的成员:

127.0.0.1:6379> ZRANGEBYSCORE myzset (10 40
1) "b"
2) "c"
3) "d"

查看小于等于50的成员,并从下标为1的成员开始分页,分页大小为3,且返回的结果带有score:

127.0.0.1:6379> ZRANGEBYSCORE myzset -inf 50 WITHSCORES LIMIT 1 3
1) "b"
2) "20"
3) "c"
4) "30"
5) "d"
6) "40"

9、ZRANK key member:返回有序集合中指定成员的索引

如果是有序集 key 的成员,返回 member 的排名(按下标从0开始);如果不是有序集 key 的成员,返回 nil 。

127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "e"
10) "50"
11) "f"
12) "60"
127.0.0.1:6379> ZRANK myzset d
(integer) 3
127.0.0.1:6379> ZRANK myzset ff
(nil)

10、ZREM key member [member ...]:移除有序集合中的一个或多个成员。

返回值为移除成员的数量

127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "e"
10) "50"
11) "f"
12) "60"
127.0.0.1:6379> ZREM myzset b d ff
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "a"
2) "10"
3) "c"
4) "30"
5) "e"
6) "50"
7) "f"
8) "60"

11、ZREMRANGEBYLEX key min max:该命令用于移除有序集合中给定的字典区间的所有成员。

  • min和max两个参数参考命令ZLEXCOUNT,跟ZLEXCOUNT命令的min和max是一样的
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "a"
2) "c"
3) "e"
4) "f"
127.0.0.1:6379> ZREMRANGEBYLEX myzset - +
(integer) 4
127.0.0.1:6379> ZRANGE myzset 0 -1
(empty list or set)

 

12、 ZREMRANGEBYRANK key start stop:移除有序集合中给定的排名区间的所有成员。

新创建myzset,然后移除下标0到1区间内的成员

127.0.0.1:6379> ZADD myzset 20 b 40 d 30 c 10 a
(integer) 4
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> ZREMRANGEBYRANK myzset 0 1
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "c"
2) "d"

13、ZREMRANGEBYSCORE key min max:移除有序集中,指定分数(score)区间内的所有成员。

  • 这里的min和max参数,查询整个有序数组的最小值和最大值时可分别用-inf和+inf表示
  • 最大或最小值前使用“(”时,不包括当前的分数,比如min使用(10,表示大于10的score,不使用括号时则包括当前分数即为大于等于10

创建myzset,然后移除所有成员:

127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "f"
10) "50"
127.0.0.1:6379> ZREMRANGEBYSCORE myzset -inf +inf
(integer) 5
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
(empty list or set)

移除score大于20,小于等于40的成员

127.0.0.1:6379> ZADD myzset 10 a 20 b 30 c 40 d 50 f
(integer) 5
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "f"
10) "50"
127.0.0.1:6379> ZREMRANGEBYSCORE myzset (20 40
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "a"
2) "10"
3) "b"
4) "20"
5) "f"
6) "50"

14、ZREVRANGE key start stop [WITHSCORES]:返回有序集中指定区间内的成员,分数从高到低排序。分数相同时,按字典序的逆序排列。

127.0.0.1:6379> ZADD myzset 10 a 20 b 30 c 40 d 50 e
(integer) 5
127.0.0.1:6379> ZREVRANGE myzset 0 -1 WITHSCORES
 1) "e"
 2) "50"
 3) "d"
 4) "40"
 5) "c"
 6) "30"
 7) "b"
 8) "20"
 9) "a"
10) "10"

15、 ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]:返回有序集中指定分数区间内的成员,score按照从大到小排序。分数相同时,按字典序的逆序排列。

  • max和min参数跟命令ZREMRANGEBYSCORE的max和min类似
  • 跟ZREVRANGE的区别是:ZREVRANGE按照索引查找返回,ZREVRANGEBYSCORE按照分数查找返回且支持分页。

返回分数小于等于50,大于等于20的成员:

127.0.0.1:6379> ZADD myzset 10 a 20 b 30 c 40 d 50 e
(integer) 5
127.0.0.1:6379> ZREVRANGEBYSCORE myzset 50 20 WITHSCORES
1) "e"
2) "50"
3) "d"
4) "40"
5) "c"
6) "30"
7) "b"
8) "20"

返回所有的成员:

127.0.0.1:6379> ZREVRANGEBYSCORE myzset +inf -inf WITHSCORES
 1) "e"
 2) "50"
 3) "d"
 4) "40"
 5) "c"
 6) "30"
 7) "b"
 8) "20"
 9) "a"
10) "10"

返回分数小于50,大于等于20的成员:

127.0.0.1:6379> ZREVRANGEBYSCORE myzset (50 20 WITHSCORES
1) "d"
2) "40"
3) "c"
4) "30"
5) "b"
6) "20"

16、ZREVRANK key member:返回有序集合中指定成员的排名。

有序集合的成员按分数值从大到小排序。

127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "e"
10) "50"
127.0.0.1:6379> ZREVRANK myzset c
(integer) 2
127.0.0.1:6379> ZREVRANK myzset b
(integer) 3

17、ZSCORE key member:返回有序集合中某个member的分数值。

(integer) 3
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "e"
10) "50"
127.0.0.1:6379> ZSCORE myzset b
"20"

18、ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]:计算一个或多个有序集的交集,并将结果集存储到新的有序集合 destination 中。

  • 默认情况下,结果集中的成员的分数值是所有给定集合下的成员的分数之和
  • numkeys:指定 key 的数量,且必须指定
  • 使用该WEIGHTS选项,可以为每个输入排序集指定乘法因子;使用该WEIGHTS选项,可以为每个输入排序集指定乘法因子。这意味着在传递给聚合函数之前,每个输入排序集中的每个元素的分数都乘以这个因子;当WEIGHTS未给出时,乘法因子默认为1
  • 如果指定WEIGHTS,其数量必须和numkeys一样,不能多也不能少
  • AGGREGATE,表示使用后面的函数,使用AGGREGATE后面的函数必须使用,否则报错
  • SUM返回成员分数总和、MIN返回分数最小的成员、MAX返回分数最大的成员

新增zset1、zset2两个有序集合,然后给WEIGHTS赋值3、4;如果WEIGHTS赋值2、3、4,就报错了。

我们可以看到res最终返回的结果是等于zset1的成员乘以3再加上zset2的成员乘以4。即:

11 = 1*3+2*4

22=2*3+4*4

127.0.0.1:6379> ZADD zset1 1 one 2 two
(integer) 2
127.0.0.1:6379> ZADD zset2 2 one 4 two 6 three
(integer) 3
127.0.0.1:6379> ZINTERSTORE res 2 zset1 zset2 WEIGHTS 3 4
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "11"
3) "two"
4) "22"
127.0.0.1:6379> ZINTERSTORE res 2 zset1 zset2 WEIGHTS 2 3 4
(error) ERR syntax error

再添加一个zset3,然后演示下AGGREGATE  SUM、MIN、MAX:

127.0.0.1:6379> ZADD zset3 3 one 5 two 7 three 9 four
(integer) 0
127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 AGGREGATE MIN
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 AGGREGATE MAX
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "3"
3) "two"
4) "5"
127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 AGGREGATE SUM
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "6"
3) "two"
4) "11"

再演示下WEIGHTS和AGGREGATE  SUM、MIN、MAX同时使用时:

127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 WEIGHTS 1 2 3 AGGREGATE MIN
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 WEIGHTS 1 2 3 AGGREGATE MAX
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "9"
3) "two"
4) "15"
127.0.0.1:6379> ZINTERSTORE res 3 zset1 zset2 zset3 WEIGHTS 1 2 3 AGGREGATE SUM
(integer) 2
127.0.0.1:6379> ZRANGE res 0 -1 WITHSCORES
1) "one"
2) "14"
3) "two"
4) "25"

19、ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]:计算一个或多个有序集的并集,并将结果集存储到新的有序集合 destination 中。

该命令跟ZINTERSCORE类似,唯一的区别是一个是计算交集,一个时计算并集。参数的用法都是一样的。小伙伴们可以按照求交集演示的数据,操作看看,我这里就不一一演示了。

127.0.0.1:6379> ZUNIONSTORE res2 3 zset1 zset2 zset3
(integer) 4
127.0.0.1:6379> ZRANGE res2 0 -1 WITHSCORES
1) "one"
2) "6"
3) "four"
4) "9"
5) "two"
6) "11"
7) "three"
8) "13"

20、ZSCAN key cursor [MATCH pattern] [COUNT count]:迭代返回有序集合中的元素(包括元素成员和元素分值)。

这个命令跟之前的SCAN、HSCAN类似。

  • cursor - 游标。
  • pattern - 匹配的模式。
  • count - 指定从数据集里返回多少元素,默认值为 10 。
127.0.0.1:6379> ZRANGE res2 0 -1 WITHSCORES
1) "one"
2) "6"
3) "four"
4) "9"
5) "two"
6) "11"
7) "three"
8) "13"
127.0.0.1:6379> ZSCAN res2 0 MATCH 'o*' COUNT 10
1) "0"
2) 1) "one"
   2) "6"

好了,Redis的有序集合的一些介绍和命令就介绍到这里,你学废了吗?没废的话,那就赶紧卷起来吧。。。

redis 循环队列 redis zset遍历_最小值