各位大佬晚上好,今天我们来学习下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的有序集合的一些介绍和命令就介绍到这里,你学废了吗?没废的话,那就赶紧卷起来吧。。。