本文来说下Redis数据结构之集合
有序集合和集合类似,只是说它是有序的,和无序集合的主要区别在于每一个元素除了值之外,它还会多一个分数。
有序集合中的元素不能重复,但是可以排序,是有序的。它给每个元素设置一个分数(score)作为排序的依据,有序集合提供了获取指定分数和元素范围查询,计算成员排名。
列表、集合、有序集合三者对比:
官网:https://redis.io/commands#sorted_set
有序集合和无序集合的命令是接近的,只是在这些命令的基础上,会增加对于排序的操作,这些是我们在使用的时候需要注意的细节.
有些时候 Redis 借助数据区间的表示方法来表示包含或者不包含,比如在数学的区间表示中[2,5 ]表示包含 2,但是不包含 5 的 区间。
添加成员(zadd):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
(0.86s)
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"
127.0.0.1:6379>
计算成员个数(zcard):zcard的时间复杂度为O(1)
127.0.0.1:6379> zcard user:ranking
(integer) 6
127.0.0.1:6379>
计算某个成员分数(zscore)
127.0.0.1:6379> zscore user:ranking mike
"91"
127.0.0.1:6379>
计算成员排名(zrank)
排序默认是从0开始。
127.0.0.1:6379> zrank user:ranking mike
(integer) 1
127.0.0.1:6379> zrank user:ranking kris
(integer) 0
127.0.0.1:6379>
删除成员(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"
5) "tom"
127.0.0.1:6379>
增加成员的分数(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"
9) "tom"
10) "251"
127.0.0.1:6379> zincrby user:ranking 9 mike
"100"
127.0.0.1:6379>
返回指定排名范围的成员(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"
9) "tom"
10) "251"
127.0.0.1:6379> zrevrange user:ranking 0 -1 withscores
1) "tom"
2) "251"
3) "martin"
4) "250"
5) "frank"
6) "200"
7) "mike"
8) "100"
9) "kris"
10) "1"
127.0.0.1:6379>
返回指定分数范围的成员(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) "tom"
2) "251"
3) "martin"
4) "250"
5) "frank"
6) "200"
7) "mike"
8) "100"
127.0.0.1:6379>
返回指定分数范围成员个数(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"
9) "tom"
10) "251"
127.0.0.1:6379> zcount user:ranking 100 200
(integer) 2
127.0.0.1:6379>
删除指定排名内的升序元素(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"
9) "tom"
10) "251"
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"
3) "tom"
4) "251"
127.0.0.1:6379>
删除指定分数范围的成员(zremrangebyscore)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "martin"
2) "250"
3) "tom"
4) "251"
127.0.0.1:6379> zremrangebyscore user:ranking 200 500
(integer) 2
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
(empty list or set)
127.0.0.1:6379>
添加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"
127.0.0.1:6379>
交集:zinterstore destination numkeys key [key …] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
·destination:交集计算结果保存到这个键。
·numkeys:需要做交集计算键的个数。
·key[key…]:需要做交集计算的键。
·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"
127.0.0.1:6379>
并集
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"
127.0.0.1:6379>
元素个数小于(默认是128),同时元素的值都小于(默认是64字节),redis会采用ziplist,可以有效减少内存的使用。
元素个数较少,且元素较小时候,
127.0.0.1:6379> zadd a 1 b
(integer) 1
127.0.0.1:6379> object encoding a
"ziplist"
127.0.0.1:6379>
当ziplist条件不满足的时候,redis会采用skiplist,因为此时ziplist的读写效率会下降。
元素个数超过128个,内部编码会变为skiplist
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"
排行版系统、记录用户每天上传视频的排行版。
添加用户赞数
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
127.0.0.1:6379>
取消用户赞数
127.0.0.1:6379> zrem user:ranking:2019_11_26 mike
(integer) 1
127.0.0.1:6379>
展示获取赞数前十名
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"
127.0.0.1:6379>
展示用户信息及用户分数
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"
127.0.0.1:6379>
本文详细介绍了Redis数据结构之有序集合,后面会对跳表以及zset的底层数据结构等相关知识进行更加详细的分析。