当前位置:   article > 正文

05- Redis 中的 Zset 数据类型和应用场景

05- Redis 中的 Zset 数据类型和应用场景

1. 介绍

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

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

2. 内部实现

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

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;

  • 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;

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

3. 常用命令

Zset 常用操作:

  1. # 往有序集合 key 中加入带分值元素
  2. ZADD key score member [[score member] ...]
  3. # 往有序集合 key 中删除元素
  4. ZREM key member [member ...]
  5. # 返回有序集合 key 中元素 member 的分值
  6. ZSCORE key member
  7. # 返回有序集合 key 中元素个数
  8. ZCARD key
  9. # 为有序集合 key 中元素 member 的分值加上 increment
  10. ZINCRBY key increment member
  11. # 正序获取有序集合 keystart 下标到 stop 下标的元素
  12. ZRANGE key start stop [WITHSCORES]
  13. # 倒序获取有序集合 keystart 下标到 stop 下标的元素
  14. ZREVRANGE key start stop [WITHSCORES]
  15. # 返回有序集合中指定分数区间内的成员,分数由低到高排序
  16. ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
  17. # 返回指定成员区间内的成员,按字典正序排列,分数必须相同
  18. ZRANGEBYLEX key min max [LIMIT offset count]
  19. # 返回指定成员区间内的成员,按字典倒序排列,分数必须相同
  20. ZREVRANGEBYLEX key max min [LIMIT offset count]

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

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

4. 应用场景

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

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

4.1 排行榜

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

我们以博文点赞排名为例,现在有五篇博文,分别获得赞为 200、40、100、50、150。

  1. # arcticle:1 文章获得了200个赞
  2. > ZADD ranking 200 arcticle:1
  3. (integer) 1
  4. # arcticle:2 文章获得了40个赞
  5. > ZADD ranking 40 arcticle:2
  6. (integer) 1
  7. # arcticle:3 文章获得了100个赞
  8. > ZADD ranking 100 arcticle:3
  9. (integer) 1
  10. # arcticle:4 文章获得了50个赞
  11. > ZADD ranking 50 arcticle:4
  12. (integer) 1
  13. # arcticle:5 文章获得了150个赞
  14. > ZADD ranking 150 arcticle:5
  15. (integer) 1

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

  1. > ZINCRBY ranking 1 arcticle:4
  2. "51"

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

  1. > ZSCORE ranking arcticle:4
  2. "51"

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

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

获取 100 赞到 200 赞的文章,可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):

  1. > ZRANGEBYSCORE ranking 100 200 WITHSCORES
  2. 1) "arcticle:3"
  3. 2) "100"
  4. 3) "arcticle:5"
  5. 4) "150"
  6. 5) "arcticle:1"
  7. 6) "200"

4.2 电话、姓名排序

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

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

1、电话排序

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

  1. > ZADD phone 0 13100111100 0 13110114300 0 13132110901
  2. (integer) 3
  3. > ZADD phone 0 13200111100 0 13210414300 0 13252110901
  4. (integer) 3
  5. > ZADD phone 0 13300111100 0 13310414300 0 13352110901
  6. (integer) 3

获取所有号码:

  1. > ZRANGEBYLEX phone - +
  2. 1) "13100111100"
  3. 2) "13110114300"
  4. 3) "13132110901"
  5. 4) "13200111100"
  6. 5) "13210414300"
  7. 6) "13252110901"
  8. 7) "13300111100"
  9. 8) "13310414300"
  10. 9) "13352110901"

获取 132 号段的号码:

  1. > ZRANGEBYLEX phone [132 (133
  2. 1) "13200111100"
  3. 2) "13210414300"
  4. 3) "13252110901"

获取132、133号段的号码:

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

2、姓名排序

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

获取所有人的名字:

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

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

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

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

  1. > ZRANGEBYLEX names [C [Z
  2. 1) "Gaodeng"
  3. 2) "Jake"
  4. 3) "Toumas"

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/673586
推荐阅读
相关标签
  

闽ICP备14008679号