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 查到对应数量的记录。