redis数据类型之sorted_set
sorted_set:有序集合,在set的基础上增加score属性用来排序,在redis中,数据类型对应的命令一般以数据类型的首字母开头,但是单词s已经被string类型使用了,所以sorted_set类型的相关命令只能使用26个英文字母中的最后一个字母z来开头,所以有些人也把sorted_set称为zset。
简单使用
zadd:添加多个score/member对到键为key的有序集合中,如果member存在,则更新score。语法:ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
:
127.0.0.1:6379> zadd fruit 50 apple 40 orange 80 balana
(integer) 3
zcard:返回有序集合中元素的个数。语法:ZCARD key
:
127.0.0.1:6379> zcard fruit
(integer) 3
zount:返回有序集合中中,score值在[min, max]区间的元素个数。语法:ZCOUNT key min max
:
127.0.0.1:6379> zcount fruit 30 70
(integer) 2
zincrby:为有序集合中member的score值加上increment。语法:ZINCRBY key increment member
:
127.0.0.1:6379> zincrby fruit 5 apple
"55"
zscore:返回有序集合中member对应的score。语法:ZSCORE key member
:
127.0.0.1:6379> zscore fruit apple
"55"
zpopmax:移除并返回有序集合中分数最高的元素,可以返回多个,从大到小。语法:ZPOPMAX key [count]
:
127.0.0.1:6379> zpopmax fruit 3
1) "balana"
2) "80"
3) "apple"
4) "55"
5) "orange"
6) "40"
zpopmin:移除并返回有序集合中score最小的元素,可以返回多个,从小到大。语法:ZPOPMIN key [count]
:
127.0.0.1:6379> zadd fruit 50 apple 40 orange 80 balana
(integer) 1
127.0.0.1:6379> zpopmin fruit 3
1) "orange"
2) "40"
3) "apple"
4) "50"
5) "balana"
6) "80"
zrange:返回有序集合中索引在[start, stop]范围的元素,可以带上score,顺序为score从小到大排列。语法:ZRANGE key start stop [WITHSCORES]
:
127.0.0.1:6379> zrange fruit 0 -1 withscores
1) "orange"
2) "40"
3) "apple"
4) "50"
5) "balana"
6) "80"
zrank:返回member在有序集合中从小到大的排名。语法:ZRANK key member
:
127.0.0.1:6379> zrank fruit apple
(integer) 1
zrangebyscore:返回有序集合中score在[min, max]范围的元素。语法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
:
127.0.0.1:6379> zrangebyscore fruit 30 70 withscores
1) "orange"
2) "40"
3) "apple"
4) "50"
区间默认为闭区间[min, max],可以通过给参数前增加(符号来使用可选的开区间(小于或大于)。例如:
127.0.0.1:6379> zrangebyscore fruit (40 70
1) "apple"
127.0.0.1:6379> zrangebyscore fruit (40 (50
(empty array)
如果不知道有序集合中最低和最高的score,可以使用-inf和+inf来代替:
127.0.0.1:6379> zrangebyscore fruit -inf +inf
1) "orange"
2) "apple"
3) "balana"
可选的limit offset count
参数可以指定返回结果的数量及区间(类似MySQL中select * from table_name limit offset, count
)。注意,如果offset太大,定位offset就可能遍历整个有序集合,这会增加O(N)的复杂度。
127.0.0.1:6379> zadd fruit 50 apple 40 orange 80 balana 60 cherry 66 grape 99 lemon 88 mongo 38 ham
(integer) 8
127.0.0.1:6379> zrangebyscore fruit 40 100 limit 3 3
1) "grape"
2) "balana"
3) "mongo"
zinterstore:计算指定numkeys个有序集合的交集,并且把结果放到destination中。在指定要计算的key和其它参数之前,必须先给定key个数(numberkeys)。默认情况下,结果集中某个成员的score值是所有给定有序集合下该成员score值之和。语法:ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
:
127.0.0.1:6379> zadd xo 10 xxoo 20 ooxx 30 xoox 40 oxxo
(integer) 4
127.0.0.1:6379> zadd ox 10 ooxx 20 oxxo 30 666
(integer) 3
127.0.0.1:6379> zinterstore xx 2 xo ox
(integer) 2
127.0.0.1:6379> zrange xx 0 -1 withscores
1) "ooxx"
2) "30"
3) "oxxo"
4) "60"
使用WEIGHTS选项,可以为每个给定的有序集指定一个乘法因子,意思就是,每个给定有序集的所有成员的score值在传递给聚合函数之前都要先乘以该因子。如果WEIGHTS没有给定,默认就是1。
127.0.0.1:6379> zinterstore xx1 2 xo ox weights 2 1
(integer) 2
127.0.0.1:6379> zrange xx1 0 -1 withscores
1) "ooxx"
2) "50"
3) "oxxo"
4) "100"
使用AGGREGATE选项,可以指定并集的结果集的聚合方式。默认使用的参数SUM,可以将所有集合中某个成员的score值之和作为结果集中该成员的score值。如果使用参数MIN或者MAX,结果集就是所有集合中元素最小或最大的元素。
127.0.0.1:6379> zinterstore xx2 2 xo ox weights 2 1 aggregate min
(integer) 2
127.0.0.1:6379> zrange xx2 0 -1 withscores
1) "ooxx"
2) "10"
3) "oxxo"
4) "20"
zunionstore:计算给定的numkeys个有序集合的并集,并且把结果放到destination中。在给定要计算的key和其它参数之前,必须先给定key个数(numberkeys)。语法:ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
:
127.0.0.1:6379> zunionstore yy 2 xo ox
(integer) 5
127.0.0.1:6379> zrange yy 0 -1 withscores
1) "xxoo"
2) "10"
3) "666"
4) "30"
5) "ooxx"
6) "30"
7) "xoox"
8) "30"
9) "oxxo"
10) "60"
zrem:删除有序集合中指定的元素。语法:ZREM key member [member ...]
:
127.0.0.1:6379> zrem yy xxoo
(integer) 1
127.0.0.1:6379> zrange yy 0 -1
1) "666"
2) "ooxx"
3) "xoox"
4) "oxxo"
zremrangebyrank:删除有序集合中索引范围为[start, stop]的元素。语法:ZREMRANGEBYRANK key start stop
:
127.0.0.1:6379> zremrangebyrank yy 0 -1
(integer) 4
zremrangebyscore:删除有序集合中索引范围为[min, max]的元素。语法:ZREMRANGEBYSCORE key min max
:
127.0.0.1:6379> zremrangebyscore xx 30 60
(integer) 2
zrangebylex:返回指定成员区间内的成员,按成员字典正序排序, 分数必须相同。max是字典中排序位置较大的成员,必须以“[”开头,或者以“(”开头,可使用“+”代替,min是字典中排序位置较小的成员,必须以“[”开头,或者以“(”开头,可使用“-”代替。语法:ZRANGEBYLEX key min max [LIMIT offset count]
:
127.0.0.1:6379> zadd zset 0 a 0 aa 0 abc 0 apple 0 b 0 c 0 d 0 d1 0 dd 0 dobble 0 z 0 z1
(integer) 12
127.0.0.1:6379> zrangebylex zset - +
1) "a"
2) "aa"
3) "abc"
4) "apple"
5) "b"
6) "c"
7) "d"
8) "d1"
9) "dd"
10) "dobble"
11) "z"
12) "z1"
zrevrange:与zrange类似,按score从大到小排列。语法:ZREVRANGE key start stop [WITHSCORES]
127.0.0.1:6379> zrevrange fruit 0 3 withscores
1) "lemon"
2) "99"
3) "mongo"
4) "88"
5) "balana"
6) "80"
7) "grape"
8) "66"
zrevrank:与zrank类似,返回member在有序集合中从大到小的排名。语法:ZREVRANK key member
:
127.0.0.1:6379> zrevrank fruit mongo
(integer) 1
zrevrangebyscore:与zrangebyscore类似,返回有序集合中指定分数区间内的成员,分数由高到低排序。语法:ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
:
127.0.0.1:6379> zrevrangebyscore fruit 100 80 withscores
1) "lemon"
2) "99"
3) "mongo"
4) "88"
5) "balana"
6) "80"
zrevrangebylex:与zrangebylex类似,返回指定成员区间内的成员,按成员字典倒序排序, 分数必须相同。语法:ZREVRANGEBYLEX key max min [LIMIT offset count]
:
127.0.0.1:6379> zrevrangebylex zset (d (a
1) "c"
2) "b"
3) "apple"
4) "abc"
5) "aa"
内部编码
有序集合类型的内部编码有两种:
- ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。
- skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。
127.0.0.1:6379> object encoding fruit
"ziplist"
127.0.0.1:6379> zadd kk 10 "one string is bigger than 64 byte...............one string is bigger than 64 byte..............." 20 test
(integer) 2
127.0.0.1:6379> object encoding kk
"skiplist"
使用场景
有序集合比较典型的使用场景就是排行榜系统,例如微博的点赞数。
- 添加一篇微博的点赞数,其中id1001为微博的id:
zadd blog:star 0 id1001
- 为微博添加点赞数量:
127.0.0.1:6379> zincrby blog:star 1 id1001
"1"
- 取消微博的点赞数量:
127.0.0.1:6379> zincrby blog:star -1 id1001
"0"
- 假如微博被删除了,这时需要删除点赞数:
127.0.0.1:6379> zrem blog:star id1001
(integer) 1
- 展示点赞数最多的十篇微博:
127.0.0.1:6379> zrevrange blog:star 0 9 withscores
(empty array)
- 查询微博的点赞数:
127.0.0.1:6379> zrank blog:star id1001
(nil)