Zset

介绍

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

有序集合保留了集合不能重复的特性(分值可以重复),单不同的是,有序集合中的元素可以排序。

内部实现

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

  • 如果有序集合的元素个数小于128 个,并且每个元素的值小于64 字节是,Redis会使用压缩列表作为Zset类型的底层数据结构
  • 如果有序集合的元素不满足上面的条件,Redis会使用跳表作为Zset类型的底层数据结构

在Redis 7.0中,压缩列表的数据结构已经废弃,交由listpack数据结构来实现了。

常用命令

Zset常用操作:

# 往有序集合key中加入带分值的元素
ZADD key score member [[score member]...]
# 往有序集合key中删除元素
ZREM key member [member...]
# 返回有序集合key中元素memeber的分值
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]
# 返回指定成员区间的成员,按字典倒序排列,分数必须相同。
ZRANGEBYLEX key max min [LIMIT offset count]

Zset运算操作(相比Set类型,ZSet类型没有支持差集运算):

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

运用场景

Zset 类型(Sorted Set,有序集合) 可以根据元素的权重来排序,我们可以自己来决定每个元素的权重值。比如说,我们可以根据元素插入 Sorted Set 的时间确定权重值,先插入的元素权重小,后插入的元素权重大。

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

排行榜

有序集合比较典型的使用场景就是排行榜。例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等。

我们以博文点赞排名为例,小林发表了五篇博文,分别获得赞为 200、40、100、50、150。

# arcticle:1 文章获得了200个赞
> ZADD user:xiaolin:ranking 200 arcticle:1
(integer) 1
# arcticle:2 文章获得了40个赞
> ZADD user:xiaolin:ranking 40 arcticle:2
(integer) 1
# arcticle:3 文章获得了100个赞
> ZADD user:xiaolin:ranking 100 arcticle:3
(integer) 1
# arcticle:4 文章获得了50个赞
> ZADD user:xiaolin:ranking 50 arcticle:4
(integer) 1
# arcticle:5 文章获得了150个赞
> ZADD user:xiaolin:ranking 150 arcticle:5
(integer) 1

文章 arcticle:4 新增一个赞,可以使用 ZINCRBY 命令(为有序集合key中元素member的分值加上increment):

> ZINCRBY user:xiaolin:ranking 1 arcticle:4
"51"

查看某篇文章的赞数,可以使用 ZSCORE 命令(返回有序集合key中元素个数):

> ZSCORE user:xiaolin:ranking arcticle:4
"50"

获取小林文章赞数最多的 3 篇文章,可以使用 ZREVRANGE 命令(倒序获取有序集合 key 从start下标到stop下标的元素):

# WITHSCORES 表示把 score 也显示出来
> ZREVRANGE user:xiaolin:ranking 0 2 WITHSCORES
1) "arcticle:1"
2) "200"
3) "arcticle:5"
4) "150"
5) "arcticle:3"
6) "100"

电话、姓名排序

使用有序集合的 ZRANGEBYLEXZREVRANGEBYLEX 可以帮助我们实现电话号码或姓名的排序,我们以 ZRANGEBYLEX (返回指定成员区间内的成员,按 key 正序排列,分数必须相同)为例。

注意:不要在分数不一致的 SortSet 集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因为获取的结果会不准确。

  1. 电话排序

    我们可以将电话号码存储到 SortSet 中,然后根据需要来获取号段:

    > 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"

    获取132、133号段的号码:

    > ZRANGEBYLEX phone [132 (134
    1) "13200111100"
    2) "13210414300"
    3) "13252110901"
    4) "13300111100"
    5) "13310414300"
    6) "13352110901"
  2. 姓名排序

    > zadd names 0 Toumas 0 Jake 0 Bluetuo 0 Gaodeng 0 Aimini 0 Aidehua
    (integer) 6

    获取所有人的名字:

    > ZRANGEBYLEX names - +
    1) "Aidehua"
    2) "Aimini"
    3) "Bluetuo"
    4) "Gaodeng"
    5) "Jake"
    6) "Toumas"

    获取名字中大写字母A开头的所有人:

    > ZRANGEBYLEX names [A (B
    1) "Aidehua"
    2) "Aimini"

    获取名字中大写字母 C 到 Z 的所有人:

    > ZRANGEBYLEX names [C [Z
    1) "Gaodeng"
    2) "Jake"
    3) "Toumas"
Last modification:May 31, 2024
如果觉得我的文章对你有用,请收藏本站