一、介绍
SortedSet
从名字来看,首先它是一个 set
,即集合。同时它是一个 SortedSet
,也就是可排序的集合。
Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet从功能上来讲有些类似,但底层数据结构却差别很大。TreeSet底层是红黑树来实现的,需要定义排序方法;而 SortedSet
底层排序是根据一个固定的 score值
来排序的。
即我们在 SortedSet
中存储元素时,需要带上一个 score(得分)
,这样它就可以帮我们根据得分去排序了,底层的实现是一个跳表(SkipList)加 hash表。跳表是用来做排序的,hash表就是最基本的结构了,key是我们的元素,值是对应的score分数。
SortedSet具备下列特性:
- 可排序
- 元素不重复(毕竟是个set)
- 查询速度快(因为有哈希表,所以查询速度是比价快的;并且跳表可以完成排序的功能,也可以增加查询速度)
因为 SortedSet
具备这样的排序功能,并且查询效率也非常高,所以它经常被用来实现像排行榜这样的功能(例如top 1等)。
二、SortedSet的常见命令
这里命令比较多,但是有很多命令都是似曾相识的。
上节将 SADD
的时候,代表新增一个元素到集合中,但是 SortedSet
因为带有排名,每一个元素都要带分数。
- ZADD key score member:添加一个或多个元素到sorted set ,如果已经存在则更新其score值
- ZREM key member:删除sorted set中的一个指定元素
- ZSCORE key member : 获取sorted set中的指定元素的score值
- ZRANK key member:获取sorted set 中的指定元素的排名(排名是从0开始的)
- ZCARD key:获取sorted set中的所有元素个数
- ZCOUNT key min max:统计score值在给定范围内的所有元素的个数(根据分数值取范围,这里的最大值最小值是一个分数的范围)
- ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的
increment值
,如果传入负数,那就是减分 - ZRANGE key min max:按照score排序后,获取指定排名范围内的元素(根据名次取范围)
- ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素(这里的最大值最小值就是分数)
- ZDIFF.ZINTER.ZUNION:求差集.交集.并集
PS:count是差个数,range是差具体元素。range又分为range和rangeByScore,range是查排序后范围的元素,rangeByScore是查指定score范围内的元素。
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV(reverse反转)即可,例如:
- 升序获取sorted set 中的指定元素的排名:ZRANK key member
- 降序获取sorted set 中的指定元素的排名:ZREVRANK key memeber
我们可以通过 help @sorted_set
在命令行查看一下
Determine the index of a member in a sorted set, with scores ordered from high to low
:确定排序集中成员的索引,分数从高到低排序,即降序。
三、代码实现
需求如下
将班级的下列学生得分存入Redis的SortedSet中:
Jack 85, Lucy 89, Rose 82, Tom 95, Jerry 78, Amy 92, Miles 76
并实现下列功能:
删除Tom同学
获取Amy同学的分数
获取Rose同学的排名
查询80分以下有几个学生
给Amy同学加2分
查出成绩前3名的同学
查出成绩80分以下的所有同学
使用 ZADD
添加元素的时候,可以看见是分数在前,元素在后,并且后面有 ...
,表示可以添加多组数据。
集合名字为 stus
,表示学生。
ZADD stus 85 Jack 89 Lucy 82 Rose 95 Tom 78 Jerry 92 Amy 76 Miles
打开图形化客户端来看看,可以发现添加成功。并且可以发现,图形化客户端默认展示的就是升序的,即已经自动排序了。
127.0.0.1:6379> ZREM stus Tom # 删除Tom同学
(integer) 1
127.0.0.1:6379> ZSCORE stus Amy # 获取Amy同学的分数
"92"
127.0.0.1:6379> ZRANK stus Rose # 获取Rose同学的排名(升序)
(integer) 2
127.0.0.1:6379> ZREVRANK stus Rose # 获取Rose同学的排名(降序)
(integer) 3
PS:返回的排名是从 0
开始的
127.0.0.1:6379> ZCOUNT stus 0 80 # 查询80分以下有几个学生
(integer) 2
127.0.0.1:6379> ZINCRBY stus 2 Amy # 给Amy同学加2分
"94"
127.0.0.1:6379> ZREVRANGE stus 0 2 # 查出成绩前3名的同学,ZRANGE是升序,这里应该使用ZREVRANGE降序
1) "Amy"
2) "Lucy"
3) "Jack"
127.0.0.1:6379> ZRANGEBYSCORE stus 0 80 # 查出成绩80分以下的所有同学
1) "Miles"
2) "Jerry"