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(东部)
胜差 球队
0 BOS
1.5 CLE
3.5 TOR
5 WAS
6.5 DET
7.5 IND
7.5 NY
8 MIL

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 key O(1)
zscore key member O(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是结果集中成员个数
时间: 2024-10-08 19:28:31

API的理解和使用——有序集合的相关文章

Redis数据操作--有序集合

| Redis 的集合以无序的方式储存多个各不相同的元素 # 用户可以快速地向集合添加元素,或者从集合里面删除元素,也可以对多个集合 进行集合运算操作,比如计算并集,交集和差集. | 元素操作 -- 添加元素     sadd key element [element ...]     # 将一个或多个元素添加到给定的集合里面,已经存在于集合的元素会         自动被忽略,命令返回新添加到集合的元素数量. -- 移除元素     srem key element [element ...]

Redis中有序集合的常用命令有哪些?

本文和大家分享的主要是redis 中有序集合类型的常用命令,一起来看看吧,希望对大家 学习redis有所帮助. 一.有序集合类型 有序集合类型,大家从名字上应该就可以知道,实际上就是在集合类型上加了个有序而已.Redis 中的有序集合类型,实际上是在集合类型上,为每个元素都关联一个分数,有序实际上说的是分数有序,我们根据分数的范围获取集合及其他操作.集合的元素依然是不能够相同的,但是分数可以相同. 下面列举有序集合和类型和列表类型的相似处: ① 两者都是有序的(废话!) ② 两者都可以获得某一范

Redis有序集合数据类型操作命令

sorted sets类型及操作 sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset(有序集合)会自动重新按新的值调整顺序.可以理解为有两列的mysql表,一列存value,一列存顺序.操作中key理解为zset的名字. zset的方法: zadd:向名称为key的zset中添加元素member,score用于排序.如果该元素存在,则更新其顺序 127.0.0.1:6379> zadd myzset 1 o

15天玩转redis —— 第六篇 有序集合类型

今天我们说一下Redis中最后一个数据类型 “有序集合类型”,回首之前学过的几个数据结构,不知道你会不会由衷感叹,开源的世界真好,写这 些代码的好心人真的要一生平安哈,不管我们想没想的到的东西,在这个世界上都已经存在着,曾几何时,我们想把所有数据按照数据结构模式组成 后灌输到内存中,然而为了达到内存共享的方式,不得不将这块内存包装成wcf单独部署,同时还要考虑怎么序列化,何时序列互的问题,烦心事太多 太多...后来才知道有redis这么个吊毛玩意,能把高级的,低级的数据结构单独包装到一个共享内存

六、Redis 基础命令--有序集合

1.有序集合是由散列表和跳跃表实现的,所以即使元素再多,获取中间的元素速度也很快. 2.有序集合为集合中的每个元素都关联了一个分数. 3.有序集合与列表的对比 相同点: 都是有序的,都可以获取某一个范围的元素 不同点: 1.列表是采用双向链表实现的,所以获取接近两端的数据很快,获取中间数据会很慢. 2.有序集合则采用的是散列表和跳跃表(百度好理解) 3.列表中不能调整某个元素的位置,但是集合可以,通过更改分数. 4.有序集合更耗费内存 4.ZADD 添加元素,返回新添加的个数 (不含已经有的)

【Redis源码剖析】 - Redis数据类型之有序集合zset

原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/article/details/51231967 这周事情比较多,原本计划每周写两篇文章的任务看来是完不成了.今天为大家带来有序集合zset的源码分析. Redis中的zset主要支持以下命令: zadd.zincrby zrem.zremrangebyrank.zremrangebyscore.zremrangebyrank zrange.zrevrange.zrangebyscore.zrevrangebys

[Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合

对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置不同的属性与顺序无关,都会以大致相同的效率产生相同的结果.也就是说访问属性a和访问属性b,没有哪个访问更快之说.ES标准并未规定属性存储的任何特定顺序,甚至于枚举对象也未涉及.for...in循环会挑选一定的顺序来枚举对象的属性,标准允许js引擎自由选择一个顺序,它们的选择会微妙地改变程序行为.如要

Redis 四:存储类型之有序集合

有序集合似乎更大的操作是由于加了一个叫做“分子”的东西 事实上就好像普通的数据,只是为这个数据加了一个纯数字的标识, 通过操作这些标识来得到我们想要的数据! 分子可以是整形,也可以是双精度浮点型: ==================================================== 1.zadd num 100 a 80 b 70 c 添加一个叫num的有序集合,a元素为100分,b元素为80分.... 2.zscore num a 获取num集合中元素名为a的分子 ====

Redis常用命令(三)有序集合键、HyperLogLog键

zet 有序集合,元素为string类型,元素具有唯一性,不重复.每个元素都会关联一个double类型的score,表示权重,通过权重将元素从小到大排序.没有修改操作,虽然每个元素必不相同,但是score可以相同 zadd key score1 member1 score2 member2 ...  # 添加 zadd fruits 1.0 apple 2.4 banana 4 watermelon 5 orange # 返回指定范围内的元素,索引从左侧开始,第一个元素为0, # 索引可以是负数