API的理解和使用——有序集合

有序集合常用的命令
命令功能
zadd key score member [score member … ]添加元素
zcard key计算成员个数
zscore key member计算某个成员分数

zrank      key member

zrevrank key member

计算成员排名
zrem key member [member …]删除成员
zincrby key increment member增长成员分数

zrange      key start end [withscores]

zrevrabge key start end [withscores]

返回指定排名范围内的成员

zrangebyscore      key min max [withscores]

zrevrangebyscore key max min [withscores]

返回指定分数范围内的成员
zcount返回指定分数范围内成员个数
zremrangebyrank key start end删除指定排名内的升序元素
zremrangebyscore key min max删除指定分数范围内的成员
zinterstore destination numkeys key [key …]交集
zunionstore destination numkeys key [key …]并集

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,

它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序

但是它和列表使用索引小标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。

有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能,合理的利用有序集合,能帮助我们在实际开发中解决很多问题。

有序集合中的元素不能重复,但是score可以重复,就和一个班里的同学学号不能重复,但是考试成绩可以相同一样。

下面给出列表、集合、有序集合三者的异同点。

列表、集合和有序集合比较
数据结构是否允许重复元素是否有序有序实现方式应用场景
列表索引时间轴、消息队列
集合标签
有序集合score排行榜系统

 

 

 

 

 

下面按照集合内和集合外两个维度对有序集合的命令进行介绍。

先给出一个有序集合:NBA某一天的排名

east(东部)
胜差球队
0BOS
1.5CLE
3.5TOR
5WAS
6.5DET
7.5IND
7.5NY
8MIL

 

 

 

 

 

 

 

 

 

1.集合内操作

(1)添加成员

命令:zadd key score member [score member … ]

127.0.0.1:6379> zadd NBA:east 0 BOS 1.5 CLE 3.5 TOR 5 WAS 6.5 DET
(integer) 5   #返回结果为成功添加成员个数
127.0.0.1:6379> zadd NBA:east 7.5 IND 7.5 NY 8 MIL
(integer) 3

有关zadd命令有两点需要注意:

第一,Redis3.2为zadd命令添加了nx、xx、ch、incr4个选项:

  • nx:member必须不存在,才可以设置成功,用于添加
  • xx:member必须存在,才可以设置成功,用于更新
  • ch:返回此次操作后,有序集合元素和分数发生变化的个数
  • incr:对score做增加,相当于后面介绍的zincrby

第二,有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度为O(log(n)),sadd的时间复杂度为O(1)。

127.0.0.1:6379> zcard NBA:east
(integer) 8

 

(2)计算成员个数

命令:zcard key

与集合类型scard命令一样,返回集合的个数,zcard的时间复杂度为O(1)。

127.0.0.1:6379> zcard NBA:east
(integer) 8

 

(3)计算某个成员的分数

命令:zscore key member

返回某个成员的分数,注意与排名分开,如果成员不存在则返回nil:

127.0.0.1:6379> zscore NBA:east IND
"7.5"
127.0.0.1:6379> zscore NBA:east DET
"6.5"

 

(4)计算成员的排名

命令:

zrank key member
zrevrank key member

zrank是分数从低到高返回排名。zrevrank反之。

复制代码
127.0.0.1:6379> zrank NBA:east CLE
(integer) 1
127.0.0.1:6379> zrank NBA:east BOS  #从0开始
(integer) 0
127.0.0.1:6379> zrevrank NBA:east BOS
(integer) 7
127.0.0.1:6379> zrevrank NBA:east CLE
(integer) 6
复制代码

 

(5)增加成员的分数

命令:zincrby key increment member

zincrby返回元素修改之后的分数:

127.0.0.1:6379> zscore NBA:east TOR   
"3.5"
127.0.0.1:6379> zincrby NBA:east 1 TOR  #又输了场
"4.5"

 

(6)返回指定排名范围内的成员

命令:

zrange key start end [withscores]
zrevrange key start end [withscores]

有序集合是按照分值排名的,zrange是从低到高返回,zrevrange反之。

下面返回胜差最小,排名前三的,如果加上withscores选项,同时会返回成员分数:

复制代码
127.0.0.1:6379> zrange NBA:east 0 2 #取前三个
1) "BOS"
2) "CLE"
3) "TOR"
127.0.0.1:6379> zrange NBA:east 0 2 withscores  #附带分数
1) "BOS"
2) "0"
3) "CLE"
4) "1.5"
5) "TOR"
6) "4.5"
127.0.0.1:6379> zrevrange NBA:east 0 2 withscores #反向取
1) "MIL"
2) "8"
3) "NY"
4) "7.5"
5) "IND"
6) "7.5"
复制代码

 

(7)返回指定分数范围内的成员

命令:

zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offset count]

其中zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。

复制代码
127.0.0.1:6379> zrangebyscore NBA:east 3 6 #正着取分数3-6
1) "TOR"
2) "WAS"
127.0.0.1:6379> zrangebyscore NBA:east 3 6 withscores
1) "TOR"
2) "4.5"
3) "WAS"
4) "5"

127.0.0.1:6379> zrevrangebyscore NBA:east 2 0 withscores
1) "CLE"
2) "1.5"
3) "BOS"  #反着取也就反着显示
4) "0"
复制代码

同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大:

复制代码
127.0.0.1:6379> zrangebyscore NBA:east (6 +inf  withscores
1) "DET"
2) "6.5"
3) "IND"
4) "7.5"
5) "NY"
6) "7.5"
7) "MIL"
8) "8"
复制代码

 

(8)返回指定分数范围内的成员个数

命令:zcount key min max

127.0.0.1:6379> zcount NBA:east 2 5
(integer) 2
127.0.0.1:6379> zrangebyscore NBA:east 2 5
1) "TOR"
2) "WAS"

 

(9)删除成员

命令:zrem key member [member … ]

127.0.0.1:6379> zrem NBA:east MIL
(integer) 1

 

(10)删除指定排名内的升序元素

命令:zremrangebyrank key start end

127.0.0.1:6379> zremrangebyrank NBA:east 0 2  #按照排名删,包含两边,所以是3
(integer) 3
127.0.0.1:6379> zcard NBA:east
(integer) 4

 

(11)删除指定分数范围内的成员

命令:zremrangebyscore key min max

#删除大于八个胜场的球队
127.0.0.1:6379> zremrangebyscore NBA:east (7 +inf
(integer) 2

 

 

2.集合间操作

将下面两个有序集合导入到Redis中。

127.0.0.1:6379> zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin 251 tom
(integer) 6
127.0.0.1:6379> zadd user:ranking:2 8 james 77 mike 625 martin 888 tom
(integer) 4

(1)交集

命令:

zinterstore destination numkeys key [key...] [weights weight [weight ... ]] [aggregate sum|min|max]

参数说明:

  • destination:交集计算结果保存到这个键。
  • numkeys:需要做交集计算键的个数。
  • key [key … ]:需要做交集计算的键。
  • weights weight [weight …]:每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,每个键的权重默认是1。
  • aggregate sum|min|max:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。

下面对两个集合取交集,weights和aggregate使用默认值:

复制代码
127.0.0.1:6379> zinterstore user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2
(integer) 3




#查看结果 127.0. 0.1: 6379> zrange user:ranking:1_inter_2 0 - 1 withscores 1) " mike " 2) " 168 " 3) " martin " 4) " 875 " 5) " tom " 6) " 1139 " #aggregate默认取和,权重为1.
复制代码

如果想让user:ranking:2的权重变为0.5,并且集合效果使用max,可以执行如下操作:

复制代码
127.0.0.1:6379> zinterstore user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 weights 1 0.5 aggregate max
(integer) 3
127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
1) "mike"
2) "91"
3) "martin"
4) "312.5"
5) "tom"
6) "444"  888/2




#再来一个例子 127.0. 0.1: 6379> zinterstore user:ranking:1_inter_2 2 user:ranking: 1 user:ranking: 2 weights 0.5 0.5 aggregate min (integer) 3 127.0. 0.1: 6379> zrange user:ranking:1_inter_2 0 - 1 withscores 1) " mike " 2) " 38.5 " 3) " martin " 4) " 125 " 5) " tom " 6) " 125.5 "
复制代码

 

(2)并集

命令:

zunionstore destination numkeys key [key ... ] [weights weight [weight ... ]] [aggregate sum|min|max]

该命令的所有参数和zinterstore是一致的,只不过是做并集计算。

下面对两个集合取并集,weights和aggregate使用默认配置

复制代码
127.0.0.1:6379> zunionstore user:ranking:1_union_2 2 user:ranking:1 user:ranking:2
(integer) 7




#相同元素相加,相异元素加进来成为一个新的元素 127.0. 0.1: 6379> zrange user:ranking:1_union_2 0 - 1 1) " kris " 2) " james " 3) " mike " 4) " frank " 5) " tim " 6) " martin " 7) " tom " #值相加 127.0. 0.1: 6379> zrange user:ranking:1_union_2 0 - 1 withscores 1) " kris " 2) " 1 " 3) " james " 4) " 8 " 5) " mike " 6) " 168 " 7) " frank " 8) " 200 " 9) " tim " 10) " 220 " 11) " martin " 12) " 875 " 13) " tom " 14) " 1139 "
复制代码

 

下面会介绍这些命令的时间复杂度,开发人员在使用对应的命令进行开发时,不仅要考虑功能性,

还要了解相应的时间复杂度,防止由于使用不当造成应用方效率下降以及Redis阻塞。




















有序集合命令的时间复杂度
命令时间复杂度
zadd key score member [score member … ]O(kxlog(n)),k是添加成员的个数,n是当前有序集合成员个数
zcard keyO(1)
zscore key memberO(1)

zrank      key member

zrevrank key member


O(log(n)),n是当前有序集合成员的个数


zrem key member [member …]
O(k*log(n)),k是删除成员的个数,n是当前有序集合成员的个数


zincrby key increment member
O(log(n)),n是当前有序集合成员个数


zrange      key start end [withscores]

zrevrabge key start end [withscores] 


O(log(n)+k),k是要获取的成员个数,n是当前有序集合成员的个数




zrangebyscore      key min max [withscores]

zrevrangebyscore key max min [withscores]


O(log(n)+k),k是要获取的成员个数,n是当前有序集合成员的个数


zcount
O(log(n)),n是当前有序集合成员个数


zremrangebyrank key start end
O(log(n)+k),k是要删除的成员个数,n是当前有序集合成员的个数


zremrangebyscore key min max
O(log(n)+k),k是要删除的成员个数,n是当前有序集合成员的个数


zinterstore destination numkeys key [key …]

O(n*k)+O(m*log(m)),n是成员数最小的有序集合成员个数,

k是有序集合的个数,m是结果集中成员个数




zunionstore destination numkeys key [key …]
O(n)+O(m*log(m)),n是所有有序集合成员个数和,m是结果集中成员个数


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值