Redis06-zset有序集合

1,146 阅读6分钟

参考

01-redis安装:how2j.cn/k/redis/red…

02-redis学习:<Redis开发与运维>(获取本书PDF见文章末)

定义

集合中的元素不能重复,但是可以排序,是有序的。它给每个元素设置一个分数(score)作为排序的依据,有序集合提供了获取指定分数和元素范围查询,计算成员排名。

列表、集合、有序集合三者对比:

命令

1.集合内

(1)添加成员(zadd)
127.0.0.1:6379> zadd key [NX|XX] [CH] [INCR] score member [score member ...]
    
·nx:member必须不存在,才可以设置成功,用于添加。
·xx:member必须存在,才可以设置成功,用于更新。
·ch:返回此次操作后,有序集合元素和分数发生变化的个数。
·incr:对score做增加,相当于后面介绍的zincrby。

单个添加和多个添加

127.0.0.1:6379> zadd user:ranking 251 tom
(integer) 1
127.0.0.1:6379> zrange user:ranking 0 -1
1) "tom"
127.0.0.1:6379> zadd user:ranking 1 kris 91 mike 200 frank 220 tim 250 martin
(integer) 5
127.0.0.1:6379> zrange user:ranking 0 -1
1) "kris"
2) "mike"
3) "frank"
4) "tim"
5) "martin"
6) "tom"
(2)计算成员个数(zcard)

zcard的时间复杂度为O(1)

127.0.0.1:6379> zcard user:ranking
(integer) 6
(3)计算某个成员分数(zscore)
127.0.0.1:6379> zscore user:ranking mike
"91"
(4)计算成员排名(zrank)

排序默认是从0开始。

127.0.0.1:6379> zrank user:ranking mike
(integer) 1
127.0.0.1:6379> zrank user:ranking kris
(integer) 0
(5)删除成员(zrem)
127.0.0.1:6379> zrem user:ranking tim
(integer) 1
127.0.0.1:6379> zrange user:ranking 0 -1
1) "kris"
2) "mike"
3) "frank"
4) "martin"
(6)增加成员的分数(zincrby)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "91"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zincrby user:ranking 9 mike
"100"
(7)返回指定排名范围的成员(zrange由高到低)(zrevrange由低到高)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "100"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zrevrange user:ranking 0 -1 withscores
1) "martin"
2) "250"
3) "frank"
4) "200"
5) "mike"
6) "100"
7) "kris"
8) "1"
(8)返回指定分数范围的成员(zrangebyscore由高到低)(zrevrangebyscore由低到高)
127.0.0.1:6379> zrangebyscore user:ranking 100 200 withscores
1) "mike"
2) "100"
3) "frank"
4) "200"
127.0.0.1:6379> zrevrangebyscore user:ranking 300 10 withscores
1) "martin"
2) "250"
3) "frank"
4) "200"
5) "mike"
6) "100"
(9)返回指定分数范围成员个数(zcount)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "100"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zcount user:ranking 100 200
(integer) 2
(10)删除指定排名内的升序元素(zremrangebyrank)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "100"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zremrangebyrank user:ranking 0 2
(integer) 3
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "martin"
2) "250"
(11)删除指定分数范围的成员(zremrangebyscore)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "tom"
2) "100"
3) "martin"
4) "250"
5) "tik"
6) "400"
7) "jkl"
8) "500"
127.0.0.1:6379> zremrangebyscore user:ranking 200 500
(integer) 3
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "tom"
2) "100"

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> zrange user:ranking:1 0 -1 withscores
 1) "kris"
 2) "1"
 3) "mike"
 4) "91"
 5) "frank"
 6) "200"
 7) "tim"
 8) "220"
 9) "martin"
10) "250"
11) "tom"
12) "251"
127.0.0.1:6379> zadd user:ranking:2 8 james 77 mike 625 martin 888 tom
(integer) 4
127.0.0.1:6379> zrange user:ranking:2 0 -1 withscores
1) "james"
2) "8"
3) "mike"
4) "77"
5) "martin"
6) "625"
7) "tom"
8) "888"
(1)交集
127.0.0.1:6379> zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]

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

127.0.0.1:6379> zinterstore s1_s2_inter 2 user:ranking:1 user:ranking:2
(integer) 3
127.0.0.1:6379> zrange s1_s2_inter 0 -1 withscores
1) "mike"
2) "168"
3) "martin"
4) "875"
5) "tom"
6) "1139"
(2)并集
127.0.0.1:6379> zunionstore s1_s2_union 2 user:ranking:1 user:ranking:2
(integer) 7
127.0.0.1:6379> zrange s1_s2_union  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"

内部编码

.ziplist(压缩列表)

元素个数小于(默认是128),同时元素的值都小于(默认是64字节),redis会采用ziplist,可以有效减少内存的使用。

1)元素个数较少,且元素较小时候,
127.0.0.1:6379> zadd a 1 b
(integer) 1
127.0.0.1:6379> object encoding a
"ziplist"
.skiplist(跳跃表)

当ziplist条件不满足的时候,redis会采用ziplist,因为此时ziplist的读写效率会下降。

1)元素个数超过128个,内部编码会变为ziplist
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3 12 e4 ... 忽略 ... 84 e129
(integer) 129
127.0.0.1:6379> object encoding zsetkey
"skiplist"
2)元素个数大于64字节时,内部编码会变成hashtable

使用场景

排行版系统、记录用户每天上传视频的排行版。

(1)添加用户赞数
127.0.0.1:6379> zadd user:ranking:2019_11_26 1 mike 2 jack 3 bok 4 you 5 lkl 6 ioj 7 iui 8 jio 9 bhb 10 ahjd 11 afs
(integer) 11
(2)取消用户赞数
127.0.0.1:6379> zrem user:ranking:2019_11_26 mike
(integer) 1
(3)展示获取赞数前十名
127.0.0.1:6379> zrevrange user:ranking:2019_11_26 0 9
 1) "afs"
 2) "ahjd"
 3) "bhb"
 4) "jio"
 5) "iui"
 6) "ioj"
 7) "lkl"
 8) "you"
 9) "bok"
10) "jack"
(4)展示用户信息及用户分数
127.0.0.1:6379> zrevrange user:ranking:2019_11_26 0 9 withscores
 1) "afs"
 2) "11"
 3) "ahjd"
 4) "10"
 5) "bhb"
 6) "9"
 7) "jio"
 8) "8"
 9) "iui"
10) "7"
11) "ioj"
12) "6"
13) "lkl"
14) "5"
15) "you"
16) "4"
17) "bok"
18) "3"
19) "jack"
20) "2"

链接:关注公众号Elevenkeep,回复redis即可获得链接。