介绍

Zset(有序集合)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成:元素值、排序值

有序集合的元素值不能重复(分值可以重复),有序集合中的元素可以排序(依据分值和字典序)

内部实现

Zset 类型的底层数据结构是由压缩列表跳表实现的:

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,使用压缩列表
  • 否则,使用跳表

在 Redis 7.0 中,压缩列表数据结构被废弃,交由 listpack 数据结构来实现

常用命令

增删改查:

# 往有序集合 key 中加入带分值元素
ZADD key score member [[score member]...]
# 往有序集合 key 中删除元素
ZREM key member [member...]
# 返回有序集合 key 中元素 member 的分值
ZSCORE key member
# 返回有序集合 key 中元素个数
ZCARD key
 
# 为有序集合 key 中元素 member 的分值加上 increment
ZINCRBY key increment member
 
# 正序获取有序集合 key 从 start 到 stop 的元素
ZRANGE key start stop [WITHSCORES]
# 倒序获取有序集合 key 从 start 到 stop 的元素
ZREVRANGE key start stop [WITHSCORES]
 
# 返回有序集合中指定分数区间内的成员,分数由低到高排序
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
 
# 返回指定成员区间内的成员,按字典正序排列, 分数必须相同
ZRANGEBYLEX key min max [LIMIT offset count]
# 返回指定成员区间内的成员,按字典倒序排列, 分数必须相同
ZREVRANGEBYLEX key max min [LIMIT offset count]

聚合计算(相比于 Set,ZSet 没有差集运算):

# 并集计算(相同元素分值相加),numberkeys 一共多少个 key,WEIGHTS 每个 key 对应的分值乘积
ZUNIONSTORE destkey numberkeys key [key...]
# 交集计算(相同元素分值相加),numberkeys 一共多少个 key,WEIGHTS 每个 key 对应的分值乘积
ZINTERSTORE destkey numberkeys key [key...]

按字典顺序获取元素

  • ZRANGEBYLEX key min max [LIMIT offset count]
    • 在有序集合中按字典顺序获取指定范围内的元素
    • key:有序集合的键
    • min:范围的最小值
      • 使用 [ 表示闭区间,使用 ( 表示开区间
      • 特殊值 - 和 + 可以用于表示负无穷和正无穷
    • max:范围的最大值
      • min
    • LIMIT offset count:用于限制返回的元素数量,从 offset 开始,最多返回 count 个元素
  • ZREVRANGEBYLEX key max min [LIMIT offset count]
    • 在有序集合中按字典顺序的逆序获取指定范围内的元素

注意:

  • 这些命令是基于字典顺序进行比较的,因此只适用于字符串类型的成员
  • 不要在分数不一致的有序集合中去使用,因为获取的结果会不准确

应用场景

Zset 类型可以根据元素的权重来排序

在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Zset

排行榜

有序集合比较典型的使用场景就是排行榜

例如,博文点赞排名:

> ZADD user:xiaolin:ranking 200 arcticle:1 # arcticle:1 文章获得了 200 个赞
> ZADD user:xiaolin:ranking 40 arcticle:2 # arcticle:2 文章获得了 40 个赞
> ZADD user:xiaolin:ranking 100 arcticle:3 # arcticle:3 文章获得了 100 个赞
> ZADD user:xiaolin:ranking 50 arcticle:4 # arcticle:4 文章获得了 50 个赞
> ZADD user:xiaolin:ranking 150 arcticle:5 # arcticle:5 文章获得了 150 个赞
 
# 文章 arcticle:4 新增一个赞
> ZINCRBY user:xiaolin:ranking 1 arcticle:4
"51"
 
# 查看某篇文章的赞数
> ZSCORE user:xiaolin:ranking arcticle:1
"200"
 
# 获取文章赞数最多的 3 篇文章
# WITHSCORES 表示把 score 也显示出来
> ZREVRANGE user:xiaolin:ranking 0 2 WITHSCORES
1) "arcticle:1"
2) "200"
3) "arcticle:5"
4) "150"
5) "arcticle:3"
6) "100"
 
# 获取 100 到 200 赞数的文章
> ZRANGEBYSCORE user:xiaolin:ranking 100 200 WITHSCORES
1) "arcticle:3"
2) "100"
3) "arcticle:5"
4) "150"
5) "arcticle:1"
6) "200"

按字典序排序

使用有序集合的 ZRANGEBYLEX 或 ZREVRANGEBYLEX 可以实现按字典序排序

# 添加电话号码(注意分数要一样)
> ZADD phone 0 13100111100 0 13110114300 0 13132110901
(integer) 3
> ZADD phone 0 13200111100 0 13210414300 0 13252110901
(integer) 3
> ZADD phone 0 13300111100 0 13310414300 0 13352110901
(integer) 3
 
# 获取所有号码
> ZRANGEBYLEX phone - +
1) "13100111100"
2) "13110114300"
3) "13132110901"
4) "13200111100"
5) "13210414300"
6) "13252110901"
7) "13300111100"
8) "13310414300"
9) "13352110901"
 
# 获取 132 号段的号码
> ZRANGEBYLEX phone [132 (133
1) "13200111100"
2) "13210414300"
3) "13252110901"