ZSet有序集合

redis的有序集合与集合一样也是String类型元素的集合,不允许有重复的元素。
每一个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合中的成员是唯一的,但是分数可以重复。
集合是通过哈希表实现的,集合中的最大元素是2的32次方减1。Zset是有序且不重复的。

注意:默认排序从小到大。

ZSet命令

1、赋值

127.0.0.1:6379> zadd rank 90 c++ 80 java 70 php 60 lua
(integer) 4

创建了一个key(名字)为rank的排行版。

2、修改分数

127.0.0.1:6379> zincrby rank 10 c++
"10"

3、通过索引区间返回指定区间内的成员

127.0.0.1:6379> zrange rank 0 -1
1) "lua"
2) "php"
3) "java"
4) "c++"
127.0.0.1:6379> zrange rank 0 1
1) "lua"
2) "php"

4、通过索引区间返回指定区间内的成员及分数

127.0.0.1:6379> zrange rank 0 -1 withscores
1) "lua"
2) "60"
3) "php"
4) "70"
5) "java"
6) "80"
7) "c++"
8) "90"

5、从大到小查询

127.0.0.1:6379> zrevrange rank 0 1 withscores
1) "c++"
2) "90"
3) "java"
4) "80"

6、获取成员数量

127.0.0.1:6379> zcard rank
(integer) 4

7、计算指定区间分数的成员数

127.0.0.1:6379> zcount rank 80 90
(integer) 2

注意这个最小分数和最大分数都是闭区间。

8、返回指定成员的索引(排名)

127.0.0.1:6379> zrank rank c++
(integer) 3
127.0.0.1:6379> zrevrank rank c++
(integer) 0

zrank是从小到大的排名,zrevrank 是从大到小的。

9、返回指定分数区间的成员

127.0.0.1:6379> zrangebyscore rank 80 90
1) "java"
2) "c++"
127.0.0.1:6379> zrevrangebyscore rank 90 80 withscores
1) "c++"
2) "90"
3) "java"
4) "80"

zrangebyscore的参数是最低分最高分,zrevrangebyscore 的参数是最高分最低分,同样是闭区间。

10、移除指定域成员

127.0.0.1:6379> zrem rank lua
(integer) 1
127.0.0.1:6379> zrange rank 0 -1
1) "php"
2) "java"
3) "c++"

11、移除给定的排名区间的所有成员

127.0.0.1:6379> zremrangebyrank rank 0 1
(integer) 2
127.0.0.1:6379> zrange rank 0 -1
1) "c++"

12、移除给定分数区间的所有成员

127.0.0.1:6379> zremrangebyscore rank 80 85
(integer) 0

13、移除整个集合排行榜

127.0.0.1:6379> del rank
(integer) 1
127.0.0.1:6379> exists rank
(integer) 0

如何处理分数相同

一般的思路都是采用实际分数和时间戳相组合结合成的最终分数作为存入ZSet的分数。
年月日时分秒xx(2x年)xx(月)xx(日)xx(时)xx(分)xx(秒),这里需要10个十进制位,如果还精确到毫秒,那么需要13个十进制位。
一个int类型最大值是2^31-1(包含±),2,147,483,647,大约是10个十进制位。
一个double类型最大值是2^63-1(包含±),9,223,372,036,854,775,807,大约是19个十进制位。
而ZSet的分数是 64位的有符号长整型,也就是约19个十进制位。

所以去掉毫秒级别13个十进制位的时间戳,还剩6个十进制位,能存储999999个数据。

有个小问题就是分数是越大排名越靠前,但是时间戳得越小排名越靠前,这里可以采用“实际分数 + 13个9 - 13位时间戳”作为分数。

参考文章
redis:zset(赋值、取值、删除、修改分数)
Redis 排行榜 相同分数根据时间优先排行

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐