Redis基础之有序集合

和set一样,sorted set也是string类型元素的集合,不同的是,为集合中的每个元素关联了一个double分数,这使得我们不仅可以完成插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最高或最低的前N个元素,获得指定分数范围内的元素等与分数有关的操作。虽然集合中的每个元素都是不同的,但是它们的分数可以相同。有序集合在某些地方和列表类型有些相似:

  • 二者都是有序的
  • 二者都可以获得某一范围内的元素
但二者也有很大的区别,应用的场景也不同。
  • 列表类型是通过链表实现的,获取靠近两端的数据极快,当元素增多后,访问链表中间的元素会减慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元素的场景。
  • 有序集合类型是使用散列表盒跳表(skip list)实现的,所以即使读取位于中间部分的元素,速度也会很快(时间复杂度为O(log(N)))。
  • 列表不能简单地调整某个元素的位置,但是有序集合可以(通过更改某个元素的值)。
  • 有序集合要比列表更耗内存。
有序集合类型算得上是Redis的5中数据类型中最高级的类型。

1. ZADD增加元素

ZADD key scroe member [score member ...]
向名称为key的zset中添加元素member, score用于排序。如果该元素已经存在,则根据score更新元素的顺序。ZADD命令的返回值是新加入到集合的元素个数(不包含之前已经有的元素)。
假设用有序的集合来模拟计分板,现在要记录Tom、Peter和David三面运动员的分数:
127.0.0.1:6379> ZADD scoreboard 89 Tom 67 Peter 100 David
(integer) 3
127.0.0.1:6379> ZADD scoreboard 76 Peter
(integer) 0
不仅可以增加整数,还可以增加双精度浮点数,其中+inf和-inf分别表示正负无穷大:
127.0.0.1:6379> ZADD testboard 17E+307 a
(integer) 1
127.0.0.1:6379> ZADD testboard 1.5 b
(integer) 1
127.0.0.1:6379> ZADD testboard +inf c
(integer) 1
127.0.0.1:6379> ZADD testboard -inf d
(integer) 1

2. ZSCORE/ZRANK获取元素分数/排名

ZSCORE/ZRANK key member
127.0.0.1:6379> ZSCORE scoreboard Peter
"76"

3. ZRANGE/ZREVRANGE获得某个范围的元素列表

ZRANGE key start stop [WITHSCORES]
ZREVRANGE  key start stop [WITHSCORES]
ZRANGE命令会按照元素的score从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)。ZRANGE命令与LRANGE命令十分相似,比如索引都是从0开始,负数代表从后往前查找(-1表示最有一个元素)。
127.0.0.1:6379> ZRANGE scoreboard 0 2
1) "Peter"
2) "Tom"
3) "David"
127.0.0.1:6379> ZRANGE scoreboard 1 -1
1) "Tom"
2) "David"
如果需要同时获得元素的分数的话可以再最后加上WITHSCORES参数,这时返回的数据格式从“元素1,元素2,...,元素n"变成”元素1,score1,元素2,score2,...,元素n,score_n",例如:
127.0.0.1:6379> ZRANGE scoreboard 1 -1 WITHSCORES
1) "Tom"
2) "89"
3) "David"
4) "100"
ZRANGE命令的时间复杂度为O(logn+m),其中n为有序集合的基数,m为返回元素的个数,当基数n很大而查询数m很小时,m可忽略不计。如果两个元素有相同的score,Redis会按照字典顺序(即“0”<"9"<"A"<"Z"<"a"<"z")来排序。再进一步,如果score都是中文怎么处理?答案是取决于中文的编码方式,如使用UTF-8编码。
ZREVRANGE命令和ZRANGE唯一不同在于,前者是按元素score的分数从大到小的顺序排列。

4. ZRANGEBYSCORE获取制定范围内的分数

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
ZRANGEBYSCORE命令参数虽然多,但是很好理解。该命令按照元素分数从小到大的顺序返回分数在min和max之间(包含min和max)的元素。如果希望分数范围不包含端点,可以在分数前加上括号“(”,比如:
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 80 100
1) "Tom"
2) "David"
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 80 (100
1) "Tom"
min和max还支持无穷大,同ZADD命令一样,-inf和+inf分别表示负无穷和正无穷。如:
127.0.0.1:6379> ZRANGEBYSCORE scoreboard (80 +inf
1) "Tom"
2) "David"
WITHSCORES参数和ZRANGE命令一样,LIMIT offset count表示在获得的元素列表的基础上向后偏移offset个元素,并且只获取前count个元素。
127.0.0.1:6379> ZADD scoreboard 56 Jerry 92 Wendy 67 Yvonne
(integer) 3
127.0.0.1:6379> ZRANGE scoreboard 0 -1 WITHSCORES
 1) "Jerry"
 2) "56"
 3) "Yvonne"
 4) "67"
 5) "Peter"
 6) "76"
 7) "Tom"
 8) "89"
 9) "Wendy"
10) "92"
11) "David"
12) "100"
想获取分数高于60分的从第二个人开始的3人:
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 60 +inf LIMIT 1 3
1) "Peter"
2) "Tom"
3) "Wendy"
ZREVRANGEBYSCORE同ZRANGEBYSCORE功能一样,只不过按照元素score从大到小的顺序给出结果,同时它的min和max参数的顺序和ZRANGEBYSCORE命令 相反


5. ZINCRBY增加某元素的分数

ZINCREBY key increment member
ZINCRBY命令可以增加一个元素的分数,当分数为负数时,表示减分,返回值是更改后的分数。例如,想给Jerry加4分,然后再减4分:
127.0.0.1:6379> ZINCRBY scoreboard 4 Jerry
"60"
127.0.0.1:6379> ZINCRBY scoreboard -4 Jerry
"56"


6. ZREM  删除元素

ZREM key member1 [member2 ...] 
ZREM会返回删除元素的个数。
127.0.0.1:6379> ZREM scoreboard Yvonne Peter
(integer) 2

7. 删除集合中排名在给定区间的元素

ZREMRANKGEBYRANK key start end 
ZREMRANKGEBYRANK会删除排名在[start, end]之间的元素,返回值为删除元素的个数,当然,start和end可以相同,表示删除特定排名的元素。

8. 删除集合中分数在给定区间的元素

ZREMRANKGEBYSCORE key start end
ZREMRANKGEBYSCORE会删除分数在[start, end]之间的元素,返回值为删除元素的个数,当然,start和end可以相同,表示删除特定分数的元素。

9. zcount 返回集合中给定区间的数量

zcount key min max
zcount会返回给定区间[min, max]的元素的数量.

10. zcard 返回集合中元素的个数

zcard key
zcard会返回集合key中元素的个数

11. 计算有序集合的交集

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight...]] [AGREGATE SUM | MIN | MAX]
ZINTERSTORE命令用来计算多个有序集合的交集并将结果存储在destination键中(同样以有序集合类型存储),返回值为destination键中的元素个数。destination键中元素的分数是由AGGREGATE参数决定的。
  1. 当AGGREGATE是SUM时(也就是默认值),destination键中元素的分数是每个参与计算的集合中该元素分数的和。
  2. 当AGGREGATE是MIN时,destination键中元素的分数是每个参与计算的集合中该元素的最小值。
  3. 当AGGREGATE是MAX时,destination键中元素是每个参与计算的集合中该元素分数的最大值。
  4. WEIGHTS参数设置每个集合的权重,每个集合在参与计算时元素的score会被乘上该集合的权重。
127.0.0.1:6379> zrange sortedSet1 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
127.0.0.1:6379> zrange sortedSet2 0 -1 WITHSCORES
1) "a"
2) "20"
3) "b"
4) "20"
127.0.0.1:6379> zinterstore sortedSets 2 sortedSet1 sortedSet2
(integer) 2
127.0.0.1:6379> zrange sortedSets 0 -1 WITHSCORES
1) "a"
2) "21"
3) "b"
4) "22"
127.0.0.1:6379> zinterstore sortedSets 2 sortedSet1 sortedSet2 AGGREGATE MIN
(integer) 2
127.0.0.1:6379> zrange sortedSets 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
127.0.0.1:6379> zinterstore sortedSets 2 sortedSet1 sortedSet2 AGGREGATE MAX
(integer) 2
127.0.0.1:6379> zrange sortedSets 0 -1 WITHSCORES
1) "a"
2) "20"
3) "b"
4) "20"
127.0.0.1:6379> zinterstore sortedSets 2 sortedSet1 sortedSet2 WEIGHTS 1 0.5
(integer) 2
127.0.0.1:6379> zrange sortedSets 0 -1 WITHSCORES
1) "a"
2) "11"
3) "b"
4) "12"


另外还有一个与ZINTERSTORE命令的用法一样,名为ZUNIONSTORE,其作用是计算集合间的并集。

总结


Redis的有序集合通常会用于游戏的排名系统中,在学习了python操作redis后,会给大家奉献出一个企业级的redis排名系统,支持20W实时排名响应,敬请期待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值