0.前言

  • 它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,这使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数

    • 注意
      • zset内部是按照升序方式来排列的
      • 如果score相同,则按照元素自身字符串的字典序来排列
        请添加图片描述
  • 有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能,合理地利⽤有序集合,可 以帮助在实际开发中解决很多问题

    • 对于ZSET来说,既可以通过member找到对应的score,也可以通过score找到匹配的member
  • 有序集合中的元素是不能重复的,但分数允许重复
    请添加图片描述


1.常见命令

1.ZADD

  • 功能添加或者更新指定的元素以及关联的分数到zset中,分数应该符合double类型,+inf/-inf作为正负极限也是合法的
  • 语法ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]
  • 相关选项
    • XX:仅仅用于更新已经存在的元素,不会添加新元素
    • NX:仅用于添加新元素,不会更新已经存在的元素
    • LT:新score小于当前score,则更新
    • GT:新score大于当前score,则更新
    • CH:默认情况下,ZADD返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数
    • INCR:此时命令类似ZINCRBY的效果,将元素的分数加上指定的分数。此时只能指定一个元素和分数
  • 返回值:本次添加成功的元素个数
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

2.ZCARD

  • 功能:获取一个zset的计数(cardinality),即zset中的元素个数
  • 语法ZCARD key
  • 返回值zset内的元素个数
  • 时间复杂度 O ( 1 ) O(1) O(1)

3.ZCOUNT

  • 功能:返回分数在minmax之间的元素个数
    • 默认情况下,minmax都是包含的,可以通过(排除 -> 表示开区间
    • 左右区间都只能用(排除,而不是左区间用(,右区间用)
  • 语法ZCOUNT key min max
  • 返回值:满足条件的元素列表个数
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

4.ZRANGE

  • 功能:返回指定区间⾥的元素,分数按照升序,带上WITHSCORES可以把分数也返回
  • 语法ZRANGE key start stop [WITHSCORES]
  • 返回值:区间内的元素列表
  • 时间复杂度 O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)

5.ZREVRANGE

  • 功能:返回指定区间⾥的元素,分数按照降序,带上WITHSCORES可以把分数也返回
    • 注意:这个命令可能在6.2.0之后废弃,并且功能合并到ZRANGE
  • 语法ZREVRANGE key start stop [WITHSCORES]
  • 返回值:区间内的元素列表
  • 时间复杂度 O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)

6.ZRANGEBYSCORE

  • 功能:返回分数在minmax之间的元素,默认情况下,minmax都是包含的,可以通过(排除
    • 注意:这个命令可能在6.2.0之后废弃,并且功能合并到ZRANGE
  • 语法ZRANGEBYSCORE key min max [WITHSCORES]
  • 返回值:区间内的元素列表
  • 时间复杂度 O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)

7.ZPOPMAX

  • 功能:删除并返回分数最高的count个元素
  • 语法ZPOPMAX key [count]
  • 返回值:分数和元素列表
  • 时间复杂度 O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)M)

8.BZPOPMAX

  • 功能ZPOPMAX的阻塞版本
  • 语法BZPOPMAX key [key ...] timeout
    • timeout:单位为秒,支持浮点数
  • 返回值:元素列表
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

9.ZPOPMIN

  • 功能:删除并返回分数最低的count个元素
  • 语法ZPOPMIN key [count]
  • 返回值:分数和元素列表
  • 时间复杂度 O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)M)

10.BZPOPMIN

  • 功能ZPOPMIN的阻塞版本
  • 语法BZPOPMIN key [key ...] timeout
  • 返回值:元素列表
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

11.ZRANK

  • 功能:返回指定元素的排名,升序
  • 语法ZRANK key member
  • 返回值:排名
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

12.ZREVRANK

  • 功能:返回指定元素的排名,降序
  • 语法ZREVRANK key member
  • 返回值:排名
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

13.ZSCORE

  • 功能:返回指定元素的分数
  • 语法ZSCORE key member
  • 返回值:分数
  • 时间复杂度 O ( 1 ) O(1) O(1)

14.ZREM

  • 功能:删除指定元素
  • 语法ZREM key member [member ...]
  • 返回值:本次操作删除的元素个数
  • 时间复杂度 O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)M)

15.ZREMRANGEBYRANK

  • 功能:按照排序,升序删除指定范围的元素,左闭右闭
  • 语法ZREMRANGEBYRANK key start stop
  • 返回值:本次操作删除的元素个数
  • 时间复杂度 O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)

16.ZREMRANGEBYSCORE

  • 功能:按照分数删除指定范围的元素,左闭右闭
  • 语法ZREMRANGEBYSCORE key min max
  • 返回值:本次操作删除的元素个数
  • 时间复杂度 O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)

17.ZINCRBY

  • 功能:为指定的元素的关联分数添加指定的分数值
  • 语法ZINCRBY key increment member
  • 返回值:增加后元素的分数
  • 时间复杂度 O ( l o g ( N ) ) O(log(N)) O(log(N))

2.集合间操作

1.有序集合的交集操作

请添加图片描述


2.ZINTERSTORE

  • 功能:求出给定有序集合中元素的交集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元 素对应的分数按照不同的聚合⽅式和权重得到新的分数
  • 语法ZINTERSTORE dest numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE]
    • 注意numkeys必须准确填写,以便后面将参数准确解析
  • 返回值:⽬标集合中的元素个数
  • 时间复杂度 O ( N ∗ K ) + O ( M ∗ l o g ( M ) ) O(N*K)+O(M*log(M)) O(NK)+O(Mlog(M)),N是输⼊的有序集合中最⼩的有序集合的元素个数,K是输⼊了 ⼏个有序集合,M是最终结果的有序集合的元素个数

3.有序集合的并集操作

请添加图片描述


4.ZUNIONSTORE

  • 功能:求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元 素对应的分数按照不同的聚合⽅式和权重得到新的分数
  • 语法ZUNIONSTORE dest numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE ]
  • 返回值:目标集合中的元素个数
  • 时间复杂度 O ( N ) + O ( M ∗ l o g ( M ) ) O(N)+O(M*log(M)) O(N)+O(Mlog(M)),N是输⼊的有序集合总的元素个数,M是最终结果的有序集合的元素个数

3.内部编码

1.ziplist(压缩链表)

  • 当有序集合的元素个数⼩于zset-max-ziplist-entries配置(默认128个), 同时每个元素的值都⼩于zset-max-ziplist-value配置(默认64字节)时,Redis会⽤ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使⽤

2.skiplist(跳表)

  • ziplist条件不满⾜时,有序集合会使⽤skiplist作为内部实现,因为此时ziplist的操作效率会下降

4.使用场景

  • 有序集合⽐较典型的使⽤场景就是排⾏榜系统
    • 例如:常⻅的⽹站上的热榜信息,榜单的维度可能是多⽅⾯的:按照时间、按照阅读量、按照点赞量
  • 示例:凭借点赞数,维护每天的热榜
    • 添加用户点赞数
      # ⽤⼾james发布了⼀篇⽂章,并获得3个赞,可以使⽤有序集合的zadd和zincrby功能
      zadd user:ranking:2024-09-01 3 james
      
      # 之后如果再获得赞,可以使⽤zincrby
      zincrby user:ranking:2022-03-15 1 james
      
    • 取消用户点赞数
      # 由于各种原因需要将⽤⼾删除,此时需要将⽤⼾从榜单中删除掉,可以使⽤zrem
      zrem user:ranking:2024-09-01 tom
      
    • 展示获取赞数最多的10个用户
      zrevrangebyrank user:ranking:2024-09-01 0 9
      
    • 展示用户信息以及用户分数:次功能将⽤⼾名作为键后缀,将⽤⼾信息保存在哈希类型中,⾄于⽤⼾的分数和排名可以使⽤zscorezrank来实现
      hgetall user:info:tom
      zscore user:ranking:2022-03-15 mike
      zrank user:ranking:2022-03-15 mike
      

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐