前言

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 ...]

命令描述

  • 将一个或多个memberscore数据对加入到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
    • NXXX参数导致未更新,返回 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)

命令格式

1
ZSCORE key member

命令描述

  • 返回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)

命令格式

1
ZCARD key

命令描述

  • 返回key对应的有序集合基数(长度)

返回值

整数值:有序集合长度或者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为有序数组中的元素个数

命令格式

1
ZCOUNT key min max

命令描述

  • 返回key对应的有序集合中,score值位于 minmax之间的元素数量

返回值

整数值:元素数量

示例

 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可以代替如下命令 ZREVRANGEZRANGEBYSCOREZREVRANGEBYSCOREZRANGEBYLEXZREVRANGEBYLEX

常用行为和选项

元素默认是由最低到最高分数排序的,相同分数的元素按照字典序升序排序。

  • REV:将排序反转,即从大到小排序,字典顺序也会反转;
  • LIMIT:返回结果集中的子集,从offset位置开始返回count个值(类似于SQL 中的*SELECT LIMIT offset, count*),当count为负数时,返回offset后的所有元素。注意:使用该参数时,需要配合BYSCORE或BYLEX使用;同时,Redis需要遍历offset个元素才能得到返回值,如果offset较大,复杂度可能会达到O(N);
  • WITHSCORES:返回元素的同时,返回score值。格式为value1,score1,…,valueN,scoreN;

索引作为查询范围

  • 命令默认按照索引作为返回元素的范围,minmax是索引范围,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值介于minmax之间的元素,由低到高排序,score值相同的按照字典序排序
  • LIMIT:返回结果集中的子集,从offset位置开始返回count个值(类似于SQL 中的*SELECT LIMIT offset, count*),当count为负数时,返回offset后的所有元素。注意:使用该参数时,Redis需要遍历offset个元素才能得到返回值,如果offset较大,复杂度可能会达到O(N);
  • WITHSCORES:返回元素的同时,返回score值。

自6.2.0版本后,该命令考虑被废弃,建议使用ZRANGE命令加BYSCORE参数。

开闭区间

  • 默认左右都是闭区间,即[min,max],如果想使用开区间,可以在索引前加上’(‘符号

    • ZRANGE zset (1 5 BYSCORE 返回 (1,5]

    • ZRANGE zset (5 (10 BYSCORE 返回 (5,10)

  • min和max可以是-inf+inf,表示负无穷和正无穷

返回值

数组:范围内按照分数升序排序的元素数组

示例

 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]

命令描述

  • 返回有序集合中特定范围内的元素,按照索引值从高到低排序,相同分数的按照字典序倒序排序返回
  • ZREVRANGEZRANGE 类似,唯一不同的是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值介于maxmin之间的元素,排序为由高到低;相同分数的也按照字典序倒序排序返回;
  • 除了排序规则不同外,ZREVRANGEBYSCOREZRANGEBYSCORE功能一致;

自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之间的元素,由高到低降序排序;
  • 除了倒序排序外,ZREVRANGEBYLEXZRANGEBYLEX命令一致;

自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