前言
Sorted Set,即有序集合,是一种类似于List(集合)和 Hash(哈希)的混合数据类型。与集合一样,有序集合由唯一的、不重复的字符串元素组成,因此在某种意义上,有序集合也是一个集合。但是集合内的元素没有排序,有序集合中的每个元素都与一个浮点值相关联,称为分数,集合中的元素会根据分数大小进行排序。由于每个元素都映射到一个值(分数),因此有序集合也类似于哈希数据类型。
有序集合的排序规则如下:
- A、B两个元素有不同的分数,如果
A.Score>B.Score
,那么 A>B
- A、B两个元素分数相同,如果按照字符串的字典排序
A>B
,那么 A>B
ZADD
可用版本:>= 1.2.0
时间复杂度: M*O(log(N)),其中M为新增的元素个数,N为有序集合中现有的元素个数
命令格式
1
|
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
|
命令描述
- 将一个或多个
member
、score
数据对加入到key
对应的有序集合中
- 如果指定的
member
已经存在有序集合中,则更新分数,同时会重新插入member
元素,以确保该元素在正确位置
- 如果
key
对应的有序集合不存在,会先创建一个空的有序集合
score
可以是整数或者双精度浮点数的字符串表示形式, +inf
和 -inf
也是有效值。
- 如果
key
对应的value类型不是Sorted Set
, 返回Error
可选参数
- XX:只更新已经存在的元素,不添加新元素
- NX:只添加新元素,不更新已有元素
- LT:新元素会添加;对于已存在元素,当新
score
值小于当前score
值时才会更新
- GT:新元素会添加;对于已存在元素,当新
score
值大于当前score
值时才会更新
- CH:改变返回值的计算逻辑。默认返回的是新添加的元素个数,提供该参数后返回被改变的元素个数:即新增的元素个数和score值被更新的元素个数之和。如果元素已经存在,且新的score值与当前score值一样,不会被计数
- INCR:提供该参数后的命令类似
ZINCRBY
,将score加上一个值,只允许提供一个member和score
注意:GT、LT 和 NX 选项是互斥的。
整数值score范围
有序集合使用double类型的64位浮点数来表示score
值,能够表示-(2^53)到+(2^53)之间的整数。在更实际的应用中,-9007199254740992 和 9007199254740992 之间的所有整数都可以完美表示。较大的整数或分数以指数形式表示,因此可能只得到较大的整数或者近似值的浮点数。
返回值
- 整数值:
- 未提供可选参数时,返回新增元素个数(不包含更新score的元素)
- 提供
CH
参数时,返回被改变的元素个数(新增和更新)
- 字符串:提供了
INCR
参数,返回字符串
- 更新成功,返回更新后元素新的
score
值
NX
、XX
参数导致未更新,返回 nil
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# 1. 不使用可选参数添加元素
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
# 遍历元素,不返回score
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "one"
2) "two"
# 遍历元素,返回score
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
# 2. 重复添加同一个元素,score会被更新
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
# 默认返回新增的元素个数
127.0.0.1:6379> zadd myzset 2 one
(integer) 0
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "2"
# 添加 CH 参数,返回被改变的元素个数
127.0.0.1:6379> zadd myzset ch 3 one
(integer) 1
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "3"
# 3. NX参数
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset NX 2 one
(integer) 0
127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
# 4. XX参数
127.0.0.1:6379> zadd myzset 3 three
(integer) 1
# four不存在,添加失败
127.0.0.1:6379> zadd myzset XX 4 four
(integer) 0
# three已存在,可以添加成功
127.0.0.1:6379> zadd myzset XX 3.1 three
(integer) 0
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "three"
4) "3.1000000000000001"
# GT、LT参数
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd myzset 5 five
(integer) 1
127.0.0.1:6379> zadd myzset 6 six
(integer) 1
# GT: 4不大于5,更新失败
127.0.0.1:6379> zadd myzset GT 4 five
(integer) 0
# LT: 4小于5,更新成功
127.0.0.1:6379> zadd myzset LT 4 six
(integer) 0
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "six"
2) "4"
3) "five"
4) "5"
|
ZSCORE
可用版本:>= 1.2.0
时间复杂度: O(1)
命令格式
命令描述
- 返回
key
对应的有序集合中,member
对应的score
值
- 如果集合不存在,或者
member
不在集合中,返回nil
返回值
字符串:member
对应的score
值
示例
1
2
3
4
5
6
7
|
127.0.0.1:6379> zadd myset 18 user1:age
(integer) 1
127.0.0.1:6379> zscore myset user1:age
"18"
# member不存在
127.0.0.1:6379> zscore myset user0:age
(nil)
|
ZCARD
可用版本:>= 1.2.0
时间复杂度: O(1)
命令格式
命令描述
返回值
整数值:有序集合长度或者0(有序集合不存在)
示例
1
2
3
4
5
6
7
8
|
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zcard myset
(integer) 2
|
ZCOUNT
可用版本:>= 2.0.0
时间复杂度: O(log(N)),N为有序数组中的元素个数
命令格式
命令描述
- 返回
key
对应的有序集合中,score
值位于 min
和 max
之间的元素数量
返回值
整数值:元素数量
示例
1
2
3
4
5
6
7
8
9
10
11
12
|
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
127.0.0.1:6379> zadd myzset 3 three
(integer) 1
127.0.0.1:6379> zadd myzset 4 four
(integer) 1
# 在2-4之间的有3个
127.0.0.1:6379> zcount myzset 2 4
(integer) 3
|
ZRANGE
可用版本:>= 1.2.0
时间复杂度:O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令变化
自6.2.0版本后,新增REV
, BYSCORE
, BYLEX
and LIMIT
参数
命令格式
1
|
ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
|
命令描述
- 返回
key
对应的有序集合中,特定范围内的元素
- ZRANGE可以执行不同类型的范围查询:根据索引(index)、分数(score)和字典顺序(lexicographical)
- 自6.2.0版本,
ZRANGE
可以代替如下命令 ZREVRANGE
、 ZRANGEBYSCORE
、 ZREVRANGEBYSCORE
、 ZRANGEBYLEX
和 ZREVRANGEBYLEX
常用行为和选项
元素默认是由最低到最高分数排序的,相同分数的元素按照字典序升序排序。
- REV:将排序反转,即从大到小排序,字典顺序也会反转;
- LIMIT:返回结果集中的子集,从
offset
位置开始返回count
个值(类似于SQL 中的*SELECT LIMIT offset, count
*),当count为负数时,返回offset
后的所有元素。注意:使用该参数时,需要配合BYSCORE或BYLEX使用;同时,Redis需要遍历offset个元素才能得到返回值,如果offset较大,复杂度可能会达到O(N);
- WITHSCORES:返回元素的同时,返回score值。格式为value1,score1,…,valueN,scoreN;
索引作为查询范围
- 命令默认按照索引作为返回元素的范围,
min
和max
是索引范围,0为第一个元素,1为第二个元素,以此类推;在这些元素中按照score由低到高排序后返回。由于Redis默认就是由低到高排序,所以该命令就是返回第min到第max的元素
- 范围首尾都是闭区间,即[min,max];
- 索引值也可以是负数,-1表示最后一个元素,-2表示倒数第二个元素,以此类推;
- 给定索引超出列表范围不会报错:
- 如果min大于列表最大索引或者大于max,返回空集合
- 如果max大于列表最大索引,Redis则令 max=最大索引
分值作为查询范围
- 当使用了
BYSCORE
参数,将会在score值介于min和max之间的元素中,按照score由低到高的顺序返回元素;
- min和max可以是
-inf
和 +inf
,表示负无穷和正无穷;
- 默认左右都是闭区间,即[min,max],如果想使用开区间,可以在索引前加上'(‘符号
- ZRANGE zset (1 5 BYSCORE 返回 (1,5]
- ZRANGE zset (5 (10 BYSCORE 返回 (5,10)
字典序作为查询范围
- 当使用了
BYLEX
参数,将会在返回字典序排序后介于min和max的元素中,按照score由低到高的顺序返回元素;
- 当有序数组中,所有元素的score值都一样时,才应该使用该参数;当元素score不一样时,使用该命令的返回结果不确定;
- min或max前需要提供’(‘或者’[‘符号,用于表示开区间或者闭区间;
- 对于min或者max,可以使用’+‘或者’-‘符号,表示正无穷或者负无穷的字符串;当有序集合中所有元素score值都相同,使用
ZRANGEBYLEX myzset - *
会返回所有元素;
返回值
数组:范围内的元素列表(如果使用了WITHSCORES参数,会同时返回score值)
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
# 插入四条数据
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 4 four
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
# 默认按照索引
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
# 默认按照索引
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
# 默认按照索引
127.0.0.1:6379> zrange myset 1 2
1) "two"
2) "three"
# REV参数,降序返回
127.0.0.1:6379> zrange myset 0 -1 rev
1) "four"
2) "three"
3) "two"
4) "one"
# WITHSCORES参数
127.0.0.1:6379> zrange myset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
# 返回score值为[1,3]之间的元素
127.0.0.1:6379> zrange myset 1 3 byscore
1) "one"
2) "two"
3) "three"
# 返回score值为[1,3)内的元素
127.0.0.1:6379> zrange myset 1 (3 byscore
1) "one"
2) "two"
# byscore,配合使用LIMIT offset count参数
127.0.0.1:6379> zrange myset 1 3 byscore limit 1 2
1) "two"
2) "three"
# 使用BYLEX参数
127.0.0.1:6379> zrange myset [a (p bylex
1) "one"
|
ZRANGEBYSCORE
可用版本:>= 1.0.5
时间复杂度: O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令格式
1
|
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
|
命令描述
- 返回score值介于
min
和max
之间的元素,由低到高排序,score值相同的按照字典序排序
- LIMIT:返回结果集中的子集,从
offset
位置开始返回count
个值(类似于SQL 中的*SELECT LIMIT offset, count
*),当count为负数时,返回offset
后的所有元素。注意:使用该参数时,Redis需要遍历offset个元素才能得到返回值,如果offset较大,复杂度可能会达到O(N);
- WITHSCORES:返回元素的同时,返回score值。
自6.2.0版本后,该命令考虑被废弃,建议使用ZRANGE命令加BYSCORE参数。
开闭区间
返回值
数组:范围内按照分数升序排序的元素数组
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
127.0.0.1:6379> zadd myzset 3 three
(integer) 1
# 返回所有元素
127.0.0.1:6379> zrangebyscore myzset -inf +inf
1) "one"
2) "two"
3) "three"
# 带有 WITHSCORES 参数
127.0.0.1:6379> zrangebyscore myzset -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zrangebyscore myzset 2 3
1) "two"
2) "three"
# 左开右闭
127.0.0.1:6379> zrangebyscore myzset (2 3
1) "three"
|
ZRANGEBYLEX
可用版本:>= 2.8.9
时间复杂度: O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令格式
1
|
ZRANGEBYLEX key min max [LIMIT offset count]
|
命令描述
- 当有序数组中所有元素的score值都相同时,该命令将元素按照字典序排序,返回第min到max之间的元素,默认升序排序;
- 如果score值不相同,返回的元素不确定;
- 命令使用C语言中的memcmp()函数,对元素由低到高排序;如果公共部分相同,长的字符串排序更高;
- LIMIT:返回结果集的子集,从
offset
位置开始返回count
个值(类似于SQL 中的*SELECT LIMIT offset, count
*),当count为负数时,返回offset
后的所有元素。注意:使用该参数时,Redis需要遍历offset个元素才能得到返回值,如果offset较大,复杂度可能会达到O(N);
自6.2.0版本后,该命令考虑被废弃,建议使用ZRANGE命令加BYLEX参数。
区间
- min或max前
必须
使用’(‘或者’[‘符号,用于表示开区间或者闭区间;
- 对于min或者max,也可以使用’+‘或者’-‘符号,表示正无穷或者负无穷的字符串;当有序集合中所有元素score值都相同,使用
ZRANGEBYLEX myzset - *
会返回所有元素;
返回值
数组:范围内按照字典序升序排序的元素数组
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
127.0.0.1:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g
(integer) 7
127.0.0.1:6379> ZRANGEBYLEX myzset - [c
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> ZRANGEBYLEX myzset - (c
1) "a"
2) "b"
127.0.0.1:6379> ZRANGEBYLEX myzset [aaa (g
1) "b"
2) "c"
3) "d"
4) "e"
5) "f"
|
ZREVRANGE
可用版本:>= 1.2.0
时间复杂度: O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令格式
1
|
ZREVRANGE key start stop [WITHSCORES]
|
命令描述
- 返回有序集合中特定范围内的元素,按照索引值从高到低排序,相同分数的按照字典序倒序排序返回
ZREVRANGE
与 ZRANGE
类似,唯一不同的是ZREVRANGE
是从高到低排序,而ZRANGE
由低到高
- 如果使用
WITHSCORES
参数,会打印出元素分值
自6.2.0版本后,ZREVRANGE命令考虑被废弃,建议使用后续的ZRANGE命令加REV参数。
返回值
数组:范围内按照降序排序的元素数组
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
127.0.0.1:6379> zadd revset 1 one
(integer) 1
127.0.0.1:6379> zadd revset 2 two
(integer) 1
127.0.0.1:6379> zadd revset 3 three
(integer) 1
127.0.0.1:6379> zadd revset 4 four
(integer) 1
127.0.0.1:6379> zrevrange revset 0 -1
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> zrevrange revset -3 -1
1) "three"
2) "two"
3) "one"
# withscore可选参数
127.0.0.1:6379> zrevrange revset 0 -1 withscores
1) "four"
2) "4"
3) "three"
4) "3"
5) "two"
6) "2"
7) "one"
8) "1"
|
ZREVRANGEBYSCORE
可用版本:>= 2.2.0
时间复杂度: O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令格式
1
|
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
|
命令描述
- 返回score值介于
max
和min
之间的元素,排序为由高到低;相同分数的也按照字典序倒序排序返回;
- 除了排序规则不同外,
ZREVRANGEBYSCORE
和ZRANGEBYSCORE
功能一致;
自6.2.0版本后,ZREVRANGE命令考虑被废弃,建议使用ZRANGE命令加BYSCORE和REV参数。
返回值
数组:范围内按照降序排序的元素数组
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
127.0.0.1:6379> zadd myzset 3 three
(integer) 1
127.0.0.1:6379> zadd myzset 4 four
(integer) 1
# 正无穷到负无穷
127.0.0.1:6379> zrevrangebyscore myzset +inf -inf
1) "four"
2) "three"
3) "two"
4) "one"
# 默认闭区间
127.0.0.1:6379> zrevrangebyscore myzset 3 1
1) "three"
2) "two"
3) "one"
# 前开后闭
127.0.0.1:6379> zrevrangebyscore myzset (3 1
1) "two"
2) "one"
|
ZREVRANGEBYLEX
可用版本:>= 2.8.9
时间复杂度: O(log(N)+M) ,N为有序数组中的元素个数,M为返回的元素个数
命令格式
1
|
ZREVRANGEBYLEX key max min [LIMIT offset count]
|
命令描述
- 当有序数组中所有元素的score值都相同时,该命令将元素按照字典序排序,返回max到min之间的元素,由高到低降序排序;
- 除了倒序排序外,
ZREVRANGEBYLEX
和ZRANGEBYLEX
命令一致;
自6.2.0版本后,ZREVRANGEBYLEX命令考虑被废弃,建议使用ZRANGE命令加BYLEX和REV参数。
返回值
数组:范围内按照降序排序的元素数组
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
127.0.0.1:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g
(integer) 7
127.0.0.1:6379> zrevrangebylex myzset + -
1) "g"
2) "f"
3) "e"
4) "d"
5) "c"
6) "b"
7) "a"
# 闭区间
127.0.0.1:6379> ZREVRANGEBYLEX myzset [c -
1) "c"
2) "b"
3) "a"
# 开区间
127.0.0.1:6379> ZREVRANGEBYLEX myzset (c -
1) "b"
2) "a"
127.0.0.1:6379> ZREVRANGEBYLEX myzset (g [aaa
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
|
总结
本文介绍了有序集合中的部分相关命令,包括
- ZADD:添加元素
- ZSCORE:获取元素score值
- ZCARD:返回集合长度
- ZCOUNT:返回给定区间的元素个数
- ZRANGE系列:升序或降序,遍历指定范围内的元素
更多
微信公众号:CodePlayer