【Redis】五大常见的数据类型之 Zset

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 我们都知道 Redis 提供了丰富的数据类型,常见的有五种:String,Hash,List,Set、Zset。今天我们就来详细的聊聊 Redis 这五大常见的数据类型之一 Zset;

前言

我们都知道 Redis 提供了丰富的数据类型,常见的有五种:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)

今天我们就来详细的聊聊 Redis 这五大常见的数据类型之一 Zset

结构类型 结构存储的值 结构读写能力
Zset 包含字符串的有序集合; 字符串成员与浮点数分数之间的有序映射;
元素的排列顺序由分数的大小决定;
添加,获取,删除单个元素;
根据分值范围或成员来获取元素;

应用场景:排序场景,比如排行榜、电话和姓名排序等。
 

概述简介

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

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


 

内部实现

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

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

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

常用命令

Zset 常用操作:

# 往有序集合 key 中加入带分值元素
# ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
127.0.0.1:6379> ZADD usr:score 63 甲 70 乙 82 丙 89 丁 92 戊
(integer) 5

# 正序获取有序集合 key 从 start 下标到 stop 下标的元素
# ZRANGE key start stop [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
127.0.0.1:6379> ZRANGE usr:score 0 -1
1) "\xe7\x94\xb2"
2) "\xe4\xb9\x99"
3) "\xe4\xb8\x99"
4) "\xe4\xb8\x81"
5) "\xe6\x88\x8a"

# 倒序获取有序集合 key 从 start 下标到 stop 下标的元素
# ZREVRANGE key start stop [WITHSCORES]
127.0.0.1:6379> ZREVRANGE usr:score 0 -1
1) "\xe6\x88\x8a"
2) "\xe4\xb8\x81"
3) "\xe4\xb8\x99"
4) "\xe4\xb9\x99"
5) "\xe7\x94\xb2"

# 往有序集合 key 中删除元素
# ZREM key member [member...]    
127.0.0.1:6379> ZREM usr:score  "\xe4\xb8\x99"
(integer) 1

# 返回有序集合 key 中元素 member 的分值
# ZSCORE key member
127.0.0.1:6379> ZSCORE usr:score "\xe4\xb9\x99"
"70"

# 返回有序集合 key 中元素个数
# ZCARD key 
127.0.0.1:6379> ZCARD usr:score
(integer) 4

# 为有序集合 key 中元素 member 的分值加上 increment
# ZINCRBY key increment member 
127.0.0.1:6379> ZINCRBY usr:score 11 "\xe4\xb9\x99" 
"81"

# 返回有序集合中指定分数区间内的成员,分数由低到高排序。
# ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
127.0.0.1:6379> ZRANGEBYSCORE usr:score 79 90
1) "\xe4\xb9\x99"
2) "\xe4\xb8\x81"

# 返回指定成员区间内的成员,按字典正序排列, 分数必须相同。
# ZRANGEBYLEX key min max [LIMIT offset count]
127.0.0.1:6379> ZADD zset 0 a 0 aa 0 abc 0 apple 0 b 0 c 0 d 0 d1 0 dd 0 dobble 0 z 0 z1
(integer) 12
127.0.0.1:6379> ZRANGEBYLEX zset - +
 1) "a"
 2) "aa"
 3) "abc"
 4) "apple"
 5) "b"
 6) "c"
 7) "d"
 8) "d1"
 9) "dd"
10) "dobble"
11) "z"
12) "z1"
127.0.0.1:6379> ZRANGEBYLEX zset - + LIMIT 0 3
1) "a"
2) "aa"
3) "abc"

# 返回指定成员区间内的成员,按字典倒序排列, 分数必须相同
# ZREVRANGEBYLEX key max min [LIMIT offset count]
127.0.0.1:6379> ZREVRANGEBYLEX zset + -
 1) "z1"
 2) "z"
 3) "dobble"
 4) "dd"
 5) "d1"
 6) "d"
 7) "c"
 8) "b"
 9) "apple"
10) "abc"
11) "aa"
12) "a"

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

# 并集计算(相同元素分值相加),numberkeys一共多少个key,WEIGHTS每个key对应的分值乘积
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

# 交集计算(相同元素分值相加),numberkeys一共多少个key,WEIGHTS每个key对应的分值乘积
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

 

应用场景

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

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

排行榜

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

我们以商品销售量为例,分别有五种商品,销售量为1243,321,98,432,2394;

# sale:1 商品的销售量为1243,以此类推
127.0.0.1:6379> ZADD mall 1243 sale:1
(integer) 1
127.0.0.1:6379> ZADD mall 321 sale:2
(integer) 1
127.0.0.1:6379> ZADD mall 98 sale:3
(integer) 1
127.0.0.1:6379> ZADD mall 432 sale:4
(integer) 1
127.0.0.1:6379> ZADD mall 2394 sale:5
(integer) 1

商品 sale:3 又卖出了一个,那么可以使用 ZINCRBY 命令(为有序集合 key 中元素 member 的分值加上 increment):

127.0.0.1:6379> ZINCRBY mall 1 sale:3
"99"

查看某个商品的销售量,可以使用 ZSCORE 命令(返回有序集合 key 中元素个数):

127.0.0.1:6379> ZSCORE mall sale:1
"1243"

获取销售量前三的商品,可以使用 ZREVRANGE 命令(倒序获取有序集合 key 从 start 下标到 stop 下标的元素):

# WITHSCORES 表示把 score 也显示出来
127.0.0.1:6379> ZREVRANGE mall 0 2 WITHSCORES
1) "sale:5"
2) "2394"
3) "sale:1"
4) "1243"
5) "sale:4"
6) "432"

获取销售量在 300 到 1000 的商品,可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):

127.0.0.1:6379> ZRANGEBYSCORE mall 300 1000
1) "sale:2"
2) "sale:4"

电话、姓名排序

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

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

1、电话排序

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

127.0.0.1:6379> ZADD phone 0 13100111100 0 13110114300 0 13132110901 
(integer) 3
127.0.0.1:6379> ZADD phone 0 13200111100 0 13210414300 0 13252110901 
(integer) 3
127.0.0.1:6379> ZADD phone 0 13300111100 0 13310414300 0 13352110901 
(integer) 3

获取所有号码:

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

获取 132 号段的号码:

127.0.0.1:6379> ZRANGEBYLEX phone [132 (133
1) "13200111100"
2) "13210414300"
3) "13252110901"

获取132、133号段的号码:

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

2、姓名排序

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

获取所有人的名字:

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

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

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

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

127.0.0.1:6379> ZRANGEBYLEX names [C [Z
1) "Gaodeng"
2) "Jake"
3) "Toumas"

 

后记

Redis 五大常见数据类型之一的 Zset 就先讲到这里了,后续还会有其他类型的讲解呢,敬请关注!

参考资料:

📝 上篇精讲: 【Redis】五大常见的数据类型之 Set
💖 我是  𝓼𝓲𝓭𝓲𝓸𝓽,期待你的关注;
👍 创作不易,请多多支持;
🔥 系列专栏: Redis
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
122 85
|
22天前
|
存储 NoSQL Redis
redis常见数据类型
Redis 是一种基于内存的键值存储数据库,支持字符串、哈希表、列表、集合及有序集合等多种数据类型,每种类型均有特定用途与适用场景,提供丰富的命令操作,适用于高速数据访问与处理。
35 5
|
1月前
|
存储 消息中间件 NoSQL
使用Java操作Redis数据类型的详解指南
通过使用Jedis库,可以在Java中方便地操作Redis的各种数据类型。本文详细介绍了字符串、哈希、列表、集合和有序集合的基本操作及其对应的Java实现。这些示例展示了如何使用Java与Redis进行交互,为开发高效的Redis客户端应用程序提供了基础。希望本文的指南能帮助您更好地理解和使用Redis,提升应用程序的性能和可靠性。
41 1
|
2月前
|
存储 消息中间件 NoSQL
Redis 数据类型
10月更文挑战第15天
45 1
|
1月前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
3月前
|
存储 消息中间件 缓存
深入探析Redis常见数据类型及应用场景
深入探析Redis常见数据类型及应用场景
74 2
|
4月前
|
NoSQL 安全 Java
Redis6入门到实战------ 三、常用五大数据类型(字符串 String)
这篇文章深入探讨了Redis中的String数据类型,包括键操作的命令、String类型的命令使用,以及String在Redis中的内部数据结构实现。
Redis6入门到实战------ 三、常用五大数据类型(字符串 String)
|
3月前
|
存储 NoSQL API
7)深度解密 Redis 的有序集合(ZSet)
7)深度解密 Redis 的有序集合(ZSet)
58 0
|
4月前
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。