Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
有序集合对象的编码可以是ziplist
或者skiplist
。同时满足以下条件时使用ziplist编码:
- 元素数量小于128个
- 所有member的长度都小于64字节
以上两个条件的上限值可通过zset-max-ziplist-entries和zset-max-ziplist-value来修改。
ziplist
编码的有序集合使用紧挨在一起的压缩列表节点来保存,第一个节点保存member,第二个保存score。ziplist内的集合元素按score从小到大排序,score较小的排在表头位置。
skiplist
编码的有序集合底层是一个命名为zset
的结构体,而一个zset结构同时包含一个字典和一个跳跃表。跳跃表按score从小到大保存所有集合元素。而字典则保存着从member到score的映射,这样就可以用O(1)的复杂度来查找member对应的score值。虽然同时使用两种结构,但它们会通过指针来共享相同元素的member和score,因此不会浪费额外的内存。
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three
(integer) 2
127.0.0.1:6379> ZRANGE myset 0 -1 //通过索引区间返回有序集合指定区间内的成员
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> ZRANGE myset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
======================================
127.0.0.1:6379> zadd age 20 chris
(integer) 1
127.0.0.1:6379> zadd age 18 mary
(integer) 1
127.0.0.1:6379> zadd age 22 tony
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE age -inf +inf withscores //通过分数返回有序集合指定区间内的成员支持负-正无穷
1) "mary"
2) "18"
3) "chris"
4) "20"
5) "tony"
6) "22"
127.0.0.1:6379> ZINCRBY age 1 chris //有序集合中对指定成员的分数加上增量 increment
"21"
127.0.0.1:6379> ZCOUNT age 0 100 //计算在有序集合中指定区间分数的成员数
(integer) 3
127.0.0.1:6379> ZCOUNT age 0 10
(integer) 0
127.0.0.1:6379> ZCOUNT age 0 18
(integer) 1
127.0.0.1:6379> ZLEXCOUNT age [chris [tony //计算有序集合中指定字典区间内成员数量
(integer) 3
======================================
返回有序集合中指定成员的索引
127.0.0.1:6379> ZRANk age mary
(integer) 0
127.0.0.1:6379> ZRANk age chris
(integer) 1
127.0.0.1:6379> ZRANk age tony
(integer) 2
======================================
127.0.0.1:6379> ZREM age tony //移除有序集合中的一个或多个成员
(integer) 1
=======================================
127.0.0.1:6379> ZREVRANGE age 0 2 withscores //返回有序集中指定区间内的成员,通过索引,分数从高到低
1) "chris"
2) "21"
3) "B"
4) "19"
5) "mary"
6) "18"
127.0.0.1:6379> ZREVRANGEBYSCORE age 20 0 withscores //返回有序集中指定分数区间内的成员,分数从高到低排序
1) "B"
2) "19"
3) "mary"
4) "18"
5) "A"
6) "16"
7) "D"
8) "11"
9) "C"
10) "10"
127.0.0.1:6379> zrevrank age A //返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
(integer) 3
127.0.0.1:6379> zrevrank age D
(integer) 4
=======================================
//ZUNIONSTORE 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。
默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和 。
127.0.0.1:6379> zrange age 0 -1
1) "C"
2) "D"
3) "A"
4) "mary"
5) "B"
6) "chris"
127.0.0.1:6379> zrange age2 0 -1
1) "D"
2) "A"
3) "B"
4) "chris"
127.0.0.1:6379> ZUNIONSTORE age3 2 age age2
(integer) 6
127.0.0.1:6379> ZRANGE age3 0 -1 withscores
1) "C"
2) "10"
3) "mary"
4) "18"
5) "D"
6) "21"
7) "A"
8) "32"
9) "B"
10) "38"
11) "chris"
12) "43"
应用场景
1、排行榜,时段排行榜,权重等 需要排序的程序
时间作为key , 点击数,评论数,等作为 score,当 score 发生变化时更新 score。利用 ZREVRANGE 或者 ZRANGE 查到对应数量的记录。