介绍
有序集合保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据
命令
命令 | 描述 | 返回值 |
zadd | zadd k-name score member[score member…] --用于将一个或多个成员元素及其分数值加入到有序集当中 | 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员 |
Zrem | ZREM k-name member [member …]–用于移除有序集中的一个或多个成员,不存在的成员将被忽略 | 被成功移除的成员的数量,不包括被忽略的成员 |
Zcard | ZCARD k-name --返回有序集合包含的成员数量 | |
Zincrby | ZINCRBY k-name increment member–将member成员的分值加1 | |
ZCOUNT | Zcount k-name min max–返回分值介于[min, max]之间的成员数量 | |
ZRANK | ZRANK k-name member–返回成员member在有序集合中的排名 | |
ZREVRANK | ZREVRANK k-name member–返回成员member在有序集合中的排名 | 成员按照分值从大到小排列 |
ZRANGE | ZRANGE k-name start stop [WITHSCORES]–返回有序集合中排名介于[start, stop]之间的成员[和分值] | |
ZREVRANGE | ZREVRANGE k-name start stop [WITHSCORES]–返回有序集合中排名介于[start, stop]之间的成员[和分值] | 成员按照分值从大到小排列 |
ZSCORE | ZSCORE k-name member–返回成员memeber的分值 | |
ZRANGEBYSCORE | ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT OFFSET count] | 返回有序集合中,分值介于[min,max]的成员 |
ZREVRANGEBYSCORE | ZREVRANGEBYSCORE key min max [WITHSCORES] [LIMIT OFFSET count] | 返回有序集合中,分值介于[min,max]的成员 |
zrevrangebyrank | ZREMRANGEBYRANK key start stop |
集合内
zadd:添加成员
作用
- 用于将一个或多个成员元素及其分数值加入到有序集当中。
- 如果某个成员已经是有序集的成员,那么更新这个成员的分数值,并通过重新插入这个成员元素,来保证该成员在正确的位置上。
- 分数值可以是整数值或双精度浮点数。
- 如果有序集合 key 不存在,则创建一个空的有序集并执行 ZADD 操作
- 当 key 存在但不是有序集类型时,返回一个错误。
注意: 在 Redis 2.4 版本以前, ZADD 每次只能添加一个元素。
语法
redis 127.0.0.1:6379> ZADD key score member [[score member] [score member] ...]
redis3.2为zadd添加了nx、xx、ch、incr四个选项
- nx:member必须不存在,才能设置成功,用于添加
- xx:member必须存在,才能设置成功,用于更新
- ch:返回此次操作后,有序集合元素和分数发生变化的个数
- incr:对socre做增加,相当于zincrby
时间复杂度
O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。
返回值
- 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
实例
# 添加单个元素
redis> ZADD page_rank 10 google.com
(integer) 1
# 添加多个元素
redis> ZADD page_rank 9 baidu.com 8 bing.com
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,且 score 值不变
redis> ZADD page_rank 10 google.com
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # 没有改变
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,但是改变 score 值
redis> ZADD page_rank 6 bing.com
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # bing.com 元素的 score 值被改变
1) "bing.com"
2) "6"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
zcard:计算成员个数
作用
返回有序集 key 的基数。
时间复杂度
O(1)
返回值
- 当 key 存在且是有序集类型时,返回有序集的基数。
- 当 key 不存在时,返回 0 。
实例
redis > ZADD salary 2000 tom # 添加一个成员
(integer) 1
redis > ZCARD salary
(integer) 1
redis > ZADD salary 5000 jack # 再添加一个成员
(integer) 1
redis > ZCARD salary
(integer) 2
redis > EXISTS non_exists_key # 对不存在的 key 进行 ZCARD 操作
(integer) 0
redis > ZCARD non_exists_key
(integer) 0
zscore:返回成员的分数
作用
- 返回有序集中,成员的分数值。
语法
redis 127.0.0.1:6379> ZSCORE key member
返回值
- 成员的分数值,以字符串形式表示。
- 如果成员元素不是有序集 key 的成员,或 key 不存在,返回 nil 。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 测试数据
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"
redis 127.0.0.1:6379> ZSCORE salary peter # 注意返回值是字符串
"3500"
ZRANK:返回指定成员的排名
作用
Redis Zrank 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
语法
redis 127.0.0.1:6379> ZRANK key member
返回值
- 如果成员是有序集 key 的成员,返回 member 的排名。
- 如果成员不是有序集 key 的成员,返回 nil 。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示所有成员及其 score 值
1) "peter"
2) "3500"
3) "tom"
4) "4000"
5) "jack"
6) "5000"
redis 127.0.0.1:6379> ZRANK salary tom # 显示 tom 的薪水排名,第二
(integer) 1
Zrevrank :返回指定成员的排名
作用
- Redis Zrevrank 命令返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
- 排名以 0 为底,也就是说, 分数值最大的成员排名为 0 。
- 使用 ZRANK 命令可以获得成员按分数值递增(从小到大)排列的排名。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 测试数据
1) "jack"
2) "2000"
3) "peter"
4) "3500"
5) "tom"
6) "5000"
redis 127.0.0.1:6379> ZREVRANK salary peter # peter 的工资排第二
(integer) 1
redis 127.0.0.1:6379> ZREVRANK salary tom # tom 的工资最高
(integer) 0
zrem:移除成员
作用
- Redis Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。
- 当 key 存在但不是有序集类型时,返回一个错误。
注意: 在 Redis 2.4 版本以前, ZREM 每次只能删除一个元素。
语法
redis 127.0.0.1:6379> ZREM key member [member ...]
返回值
被成功移除的成员的数量,不包括被忽略的成员。
实例
# 测试数据
redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 移除单个元素
redis 127.0.0.1:6379> ZREM page_rank google.com
(integer) 1
redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
# 移除多个元素
redis 127.0.0.1:6379> ZREM page_rank baidu.com bing.com
(integer) 2
redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
(empty list or set)
# 移除不存在元素
redis 127.0.0.1:6379> ZREM page_rank non-exists-element
(integer) 0
zincrby:增加成员的分数
作用
- 为有序集 key 的成员 member 的 score 值加上增量 increment 。
- 可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。
- 当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。
- 当 key 不是有序集类型时,返回一个错误
- score 值可以是整数值或双精度浮点数。
返回值
- member 成员的新 score 值,以字符串形式表示。
实例
redis> ZSCORE salary tom
"2000"
redis> ZINCRBY salary 2000 tom # tom 加薪啦!
"4000"
zrange/zrevrange
作用
- Redis Zrange 返回有序集中,指定区间内的成员。
- 其中成员的位置按分数值递增(从小到大)来排序。
- 具有相同分数值的成员按字典序(lexicographical order )来排列。
- 如果你需要成员按值递减(从大到小)来排列,请使用 ZREVRANGE 命令。
- 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
- 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
语法
redis 127.0.0.1:6379> ZRANGE key start stop [WITHSCORES]
返回值
指定区间内,带有分数值(可选)的有序集成员的列表。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示整个有序集成员
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis 127.0.0.1:6379> ZRANGE salary 1 2 WITHSCORES # 显示有序集下标区间 1 至 2 的成员
1) "tom"
2) "5000"
3) "boss"
4) "10086"
redis 127.0.0.1:6379> ZRANGE salary 0 200000 WITHSCORES # 测试 end 下标超出最大下标时的情况
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis > ZRANGE salary 200000 3000000 WITHSCORES # 测试当给定区间不存在于有序集时的情况
(empty list or set)
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 递增排列
1) "peter"
2) "3500"
3) "tom"
4) "4000"
5) "jack"
6) "5000"
redis 127.0.0.1:6379> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列
1) "jack"
2) "5000"
3) "tom"
4) "4000"
5) "peter"
6) "3500"
zrange/zrevrange:获取指定范围的元素
作用
- Redis Zrange 返回有序集中,指定区间内的成员。
- 其中成员的位置按分数值递增(从小到大)来排序。
- 具有相同分数值的成员按字典序(lexicographical order )来排列。
- 如果你需要成员按值递减(从大到小)来排列,请使用 ZREVRANGE 命令。
- 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
- 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
语法
redis 127.0.0.1:6379> ZRANGE key start stop [WITHSCORES]
返回值
指定区间内,带有分数值(可选)的有序集成员的列表。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示整个有序集成员
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis 127.0.0.1:6379> ZRANGE salary 1 2 WITHSCORES # 显示有序集下标区间 1 至 2 的成员
1) "tom"
2) "5000"
3) "boss"
4) "10086"
redis 127.0.0.1:6379> ZRANGE salary 0 200000 WITHSCORES # 测试 end 下标超出最大下标时的情况
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis > ZRANGE salary 200000 3000000 WITHSCORES # 测试当给定区间不存在于有序集时的情况
(empty list or set)
返回分数在0到100的成员.
127.0.0.1:6379> zrangebyscore user:ranking 0 100
1) "codger"
2) "hank"
3) "ann"
4) "Rico"
5) "tom"
返回分数在0到无限大的成员.
127.0.0.1:6379> zrangebyscore user:ranking 0 +inf
1) "codger"
2) "hank"
3) "ann"
4) "Rico"
5) "tom"
zcount:分数值在 min 和 max 之间的成员的数量
作用
用于计算有序集合中指定分数区间的成员数量。
语法
redis 127.0.0.1:6379> ZCOUNT key min max
返回值
分数值在 min 和 max 之间的成员的数量。
实例
redis 127.0.0.1:6379> ZADD myzset 1 "hello"
(integer) 1
redis 127.0.0.1:6379> ZADD myzset 1 "foo"
(integer) 1
redis 127.0.0.1:6379> ZADD myzset 2 "world" 3 "bar"
(integer) 2
redis 127.0.0.1:6379> ZCOUNT myzset 1 3
(integer) 4
zremrangebyscore:删除分数从min到max的成员
作用
Zremrangebyscore 命令用于移除有序集中,指定分数(score)区间内的所有成员。
语法
redis 127.0.0.1:6379> ZREMRANGEBYSCORE key min max
返回值
被移除成员的数量。
实例
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示有序集内所有成员及其 score 值
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"
redis 127.0.0.1:6379> ZREMRANGEBYSCORE salary 1500 3500 # 移除所有薪水在 1500 到 3500 内的员工
(integer) 2
redis> ZRANGE salary 0 -1 WITHSCORES # 剩下的有序集成员
1) "jack"
2) "5000"
集合间
zinterstore:交集
作用
- Redis Zinterstore 命令计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。
- 默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和。
语法
zinterstore storeKey keyNum key [key ...] [weights weight [weight...]] [aggregate sum|min|max]
参数说明:
- storeKey:交集计算结果保存到这个键下.
- keyNum:需要做交集的键的个数.
- key[key …]:需要做交集的键.
- weights weight [weight…]:每个键的权重,在做交集计算时,每个键中的每个member的分值会和这个权重相乘,每个键的权重默认为1.
- aggregate sum|min|sum:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总.默认值为sum.
实例
# 有序集 mid_test
redis 127.0.0.1:6379> ZADD mid_test 70 "Li Lei"
(integer) 1
redis 127.0.0.1:6379> ZADD mid_test 70 "Han Meimei"
(integer) 1
redis 127.0.0.1:6379> ZADD mid_test 99.5 "Tom"
(integer) 1
# 另一个有序集 fin_test
redis 127.0.0.1:6379> ZADD fin_test 88 "Li Lei"
(integer) 1
redis 127.0.0.1:6379> ZADD fin_test 75 "Han Meimei"
(integer) 1
redis 127.0.0.1:6379> ZADD fin_test 99.5 "Tom"
(integer) 1
# 交集
redis 127.0.0.1:6379> ZINTERSTORE sum_point 2 mid_test fin_test
(integer) 3
# 显示有序集内所有成员及其分数值
redis 127.0.0.1:6379> ZRANGE sum_point 0 -1 WITHSCORES
1) "Han Meimei"
2) "145"
3) "Li Lei"
4) "158"
5) "Tom"
6) "199"
zunionstore:并集
该命令的所有参数和zinterstore是一致的,只不过做的是并集计算.
内部编码
有序集合类型的内部编码有两种:
- ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplistentries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现
- skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现
使用场景
有序集合比较典型的使用场景就是排行榜系统。例如视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数
- 添加用户赞数
例如用户mike上传了一个视频,并获得了3个赞,可以使用有序集合的 zadd和zincrby功能:
zadd user:ranking:2016_03_15 mike 3
如果之后再获得一个赞,可以使用zincrby:
zincrby user:ranking:2016_03_15 mike 1
- 取消用户赞数
由于各种原因(例如用户注销、用户作弊)需要将用户删除,此时需要将用户从榜单中删除掉,可以使用zrem。例如删除成员tom:
zrem user:ranking:2016_03_15 mike
- 展示获取赞数最多的十个用户
zrevrangebyrank user:ranking:2016_03_15 0 9
- 展示用户信息以及用户分数
此功能将用户名作为键后缀,将用户信息保存在哈希类型中,至于用户的分数和排名可以使用zscore和zrank两个功能:
hgetall user:info:tom zscore user:ranking:2016_03_15 mike zrank user:ranking:2016_03_15 mike