Redis学习笔记—数据类型:有序集合(zset)

有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。

集合内操作

1.添加成员
zadd key [nx|xx] [ch] [incr] score member [score member ...]
  • nx:member必须不存在,才可以设置成功,用于添加
  • xx:member必须存在,才可以设置成功,用于更新
  • ch:返回此次操作后,有序集合元素和分数发生变化的个数
  • incr:对score做增加,相当于后面介绍的zincrby
  • 有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度为O(log(n)),sadd的时间复杂度为O(1)。

添加key为“user:ranking”的集合

127.0.0.1:6379> zadd user:ranking 150 Tom
(integer) 1
127.0.0.1:6379> zadd user:ranking 1 Charlie 14 Day 66 Ling 124 Zhang
(integer) 4
2.计算成员个数
zcard key

计算key为“user:ranking”的集合成员个数

127.0.0.1:6379> zcard user:ranking
(integer) 5
3.计算某个成员的分数
zscore key member

计算key为“user:ranking”的集合成员“Charlie”的分数

127.0.0.1:6379> zscore user:ranking Charlie
"1"
4.计算成员的排名

从低到高

zrank key member

从高到低

zrevrank key member

计算key为“user:ranking”的集合成员的排名

127.0.0.1:6379> zrank user:ranking Day
(integer) 1
127.0.0.1:6379> zrank user:ranking Charlie
(integer) 0
127.0.0.1:6379> zrank user:ranking Zhang
(integer) 3
5.删除成员
zrem key member [member ...]

删除key为“user:ranking”的集合成员“Zhang”

127.0.0.1:6379> zrem user:ranking Zhang
(integer) 1
6.增加成员的分数
zincrby key increment member

增加key为“user:ranking”的集合成员“Ling”5分

127.0.0.1:6379> zincrby user:ranking 5 Ling
"71"
7.返回指定排名范围的成员

从低到高

zrange key start end [withscores]

从高到低

zrevrange key start end [withscores]

返回key为“user:ranking”的集合指定范围和分数

127.0.0.1:6379> zrange user:ranking 0 -1
1) "Charlie"
2) "Day"
3) "Ling"
4) "Tom"
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "Charlie"
2) "1"
3) "Day"
4) "14"
5) "Ling"
6) "71"
7) "Tom"
8) "150"
8.返回指定分数范围的成员

从低到高

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

从高到低

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

返回key为“user:ranking”的集合指定分数范围的成员

127.0.0.1:6379> zrangebyscore user:ranking 10 80 withscores
1) "Day"
2) "14"
3) "Ling"
4) "71"
127.0.0.1:6379> zrevrangebyscore user:ranking 80 10 withscores
1) "Ling"
2) "71"
3) "Day"
4) "14"

min和max默认闭区间,支持开区间(小括号),-inf和+inf分别代表无限小和无限大

127.0.0.1:6379> zrangebyscore user:ranking 10 +inf withscores
1) "Day"
2) "14"
3) "Ling"
4) "71"
5) "Tom"
6) "150"
127.0.0.1:6379> zrevrangebyscore user:ranking 80 -inf withscores
1) "Ling"
2) "71"
3) "Day"
4) "14"
5) "Charlie"
6) "1"
127.0.0.1:6379> zrevrangebyscore user:ranking 71 -inf withscores
1) "Ling"
2) "71"
3) "Day"
4) "14"
5) "Charlie"
6) "1"
127.0.0.1:6379> zrevrangebyscore user:ranking (71 -inf withscores
1) "Day"
2) "14"
3) "Charlie"
4) "1"
9.返回指定分数范围的成员个数
zcount key min max

返回key为“user:ranking”的集合指定分数范围的成员个数

127.0.0.1:6379> zcount user:ranking 10 80
(integer) 2
10.删除指定排名内的升序元素
zremrangebyrank key start stop
11.删除指定分数范围的成员
zremrangebyscore key min max

集合间的操作

添加测试数据

127.0.0.1:6379> zadd user:ranking:1 1 Carlie 15 Day 67 Lin 124 Zhang
(integer) 4
127.0.0.1:6379> zadd user:ranking:2 5 Tom 35 Jerry 564 Zhang
(integer) 3
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

下面操作对user:ranking:1和user:ranking:2做交集,weights和aggregate使用了默认配置,可以看到目标键user:ranking:1_inter_2对分值做了sum操作

127.0.0.1:6379> zinterstore user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2
(integer) 1
127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
1) "Zhang"
2) "688"
2.并集
zunionstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate sum|min|max]

生成key为“user:ranking:1_union_2”的并集

127.0.0.1:6379> zunionstore user:ranking:1_union_2 2 user:ranking:1 user:ranking:2
(integer) 6
127.0.0.1:6379> zrange user:ranking:1_union_2 0 -1 withscores
1) "Carlie"
2) "1"
3) "Tom"
4) "5"
5) "Day"
6) "15"
7) "Jerry"
8) "35"
9) "Lin"
10) "67"
11) "Zhang"
12) "688"

内部编码

  • ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用
  • skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。

使用场景

排行榜系统
  1. 添加用户赞数可以使用zadd和zincrby功能
  2. 取消用户赞数,用户作弊或者注销,可以用zrem
  3. 展示排行榜使用zrevrange命令
  4. 展示用户信息或者分数可以使用zscore和zrank两个功能

发表评论

邮箱地址不会被公开。 必填项已用*标注