一、ZSet 类型介绍
ZSet(有序集合)是 Redis 数据库中的一种数据类型,它是一种无序的集合,每个元素都与一个浮点数分数相关联,使得集合中的元素可以根据分数进行排序。ZSet 也常被称为 Sorted Set。
特点和用途:
-
元素唯一性:ZSet 中的元素是唯一的,不允许重复元素存在。
-
有序性:与普通集合不同,ZSet 中的元素是有序排列的,根据元素的分数从小到大排序。
-
分数与元素关联:每个元素都与一个分数相关联,分数用于确定元素的位置。
-
高效的成员查找:Redis 提供了高效的成员查找操作,可以根据成员名字快速查找分数。
-
范围查询:ZSet 支持根据分数范围进行查询,例如获取分数在某个范围内的元素。
-
排行榜:ZSet 常用于构建排行榜,其中分数可以表示用户的得分或者其他权重值。
二、ZSet(有序集合)类型相关命令
ZSet(有序集合)是 Redis 中的一种数据类型,它类似于 Set,但每个元素都会关联一个分数(score),使得集合中的元素能够按照分数进行排序。以下是与 ZSet 相关的常见命令:
2.1 ZADD
ZADD 命令用于向有序集合中添加或更新元素以及与之关联的分数。分数必须是 double 类型,可以是正数、负数、正负无穷大等。ZADD 命令的相关选项包括:
- NX:仅用于添加新元素,不会更新已经存在的元素。
- XX:仅用于更新已经存在的元素,不会添加新元素。
- CH:默认情况下,ZADD 返回添加的元素数量,但指定这个选项后,它会返回添加和更新的元素数量。
- INCR:此选项类似于 ZINCRBY 命令,用于对指定元素的分数进行增量操作。
语法:
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
2.2 ZCARD 和 ZCOUNT
-
ZCARD:获取有序集合中元素的数量(基数)。
语法:
ZCARD key
-
ZCOUNT:计算有序集合中指定分数范围内的元素数量。
语法:
ZCOUNT key min max
2.3 ZRANGE、ZREVRANGE 和 ZRANGEBYSCORE
-
ZRANGE:按照分数从小到大的顺序,返回有序集合中指定索引范围内的元素。
语法:
ZRANGE key start stop [WITHSCORES]
-
ZREVRANGE:按照分数从大到小的顺序,返回有序集合中指定索引范围内的元素。
语法:
ZREVRANGE key start stop [WITHSCORES]
-
ZRANGEBYSCORE:根据分数范围,返回有序集合中符合条件的元素。
语法:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
2.4 ZPOPMAX 和 ZPOPMIN、BZPOPMAX 和 BZPOPMIN
-
ZPOPMAX:从有序集合中删除并返回分数最高的元素。
-
ZPOPMIN:从有序集合中删除并返回分数最低的元素。
-
BZPOPMAX:阻塞版本的 ZPOPMAX,在没有元素可弹出时会等待。
-
BZPOPMIN:阻塞版本的 ZPOPMIN,在没有元素可弹出时会等待。
语法(ZPOPMAX 和 ZPOPMIN):
ZPOPMAX key [count]
ZPOPMIN key [count]
语法(BZPOPMAX 和 BZPOPMIN):
BZPOPMAX key [key ...] timeout
BZPOPMIN key [key ...] timeout
2.5 ZRANK、ZREVRANK、ZSCORE 和 ZINCRBY
-
ZRANK:获取指定元素在有序集合中的排名(从小到大排序)。
-
ZREVRANK:获取指定元素在有序集合中的排名(从大到小排序)。
-
ZSCORE:获取指定元素在有序集合中的分数。
-
ZINCRBY:对指定元素的分数进行增减操作。
语法(ZRANK 和 ZREVRANK):
ZRANK key member
ZREVRANK key member
语法(ZSCORE):
ZSCORE key member
语法(ZINCRBY):
ZINCRBY key increment member
2.6 ZREM、ZREMRANGEBYRANK 和 ZREMRANGEBYSCORE
-
ZREM:从有序集合中移除一个或多个指定的元素。
-
ZREMRANGEBYRANK:根据排名范围移除有序集合中的元素。
-
ZREMRANGEBYSCORE:根据分数范围移除有序集合中的元素。
语法(ZREM):
ZREM key member [member ...]
语法(ZREMRANGEBYRANK):
ZREMRANGEBYRANK key start stop
语法(ZREMRANGEBYSCORE):
ZREMRANGEBYSCORE key min max
2.7 ZINTERSTORE 和 ZUNIONSTORE
-
ZINTERSTORE:计算多个有序集合的交集,并将结果存储在一个新的有序集合中。
-
ZUNIONSTORE:计算多个有序集合的并集,并将结果存储在一个新的有序集合中。
语法(ZINTERSTORE):
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
语法(ZUNIONSTORE):
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
2.8 ZSet 相关命令总结
以下是与 ZSet 类型相关的命令的总结,包括命令、作用和时间复杂度:
命令 | 作用 | 时间复杂度 |
---|---|---|
ZADD |
添加或更新有序集合中的元素和分数 | O(log(N)*M) (N 为有序集合的大小,M 为要添加/更新的元素数量) |
ZCARD |
获取有序集合中元素的数量 | O(1) |
ZCOUNT |
计算有序集合中分数范围内的元素数量 | O(log(N)) |
ZRANGE |
获取有序集合中指定索引范围的元素(升序) | O(log(N)+M) (N 为有序集合的大小,M 为返回的元素数量) |
ZREVRANGE |
获取有序集合中指定索引范围的元素(降序) | O(log(N)+M) (N 为有序集合的大小,M 为返回的元素数量) |
ZRANGEBYSCORE |
获取有序集合中符合分数范围条件的元素 | O(log(N)+M) (N 为有序集合的大小,M 为返回的元素数量) |
ZPOPMAX |
弹出并返回有序集合中分数最高的元素 | O(log(N)) |
ZPOPMIN |
弹出并返回有序集合中分数最低的元素 | O(log(N)) |
ZRANK |
获取指定元素在有序集合中的排名(升序) | O(log(N)) |
ZREVRANK |
获取指定元素在有序集合中的排名(降序) | O(log(N)) |
ZSCORE |
获取指定元素在有序集合中的分数 | O(1) |
ZINCRBY |
对指定元素的分数进行增减操作 | O(log(N)) |
ZREM |
从有序集合中移除指定的元素 | O(log(N)*M) (N 为有序集合的大小,M 为要移除的元素数量) |
ZREMRANGEBYRANK |
根据排名范围移除有序集合中的元素 | O(log(N)+M) (N 为有序集合的大小,M 为要移除的元素数量) |
ZREMRANGEBYSCORE |
根据分数范围移除有序集合中的元素 | O(log(N)+M) (N 为有序集合的大小,M 为要移除的元素数量) |
ZINTERSTORE |
计算多个有序集合的交集并存储结果 | O(NK)+O(Mlog(M)) (N 为输入有序集合的数量,K 为最小有序集合的大小,M 为输出有序集合的大小) |
ZUNIONSTORE |
计算多个有序集合的并集并存储结果 | O(NK)+O(Mlog(M)) (N 为输入有序集合的数量,K 为最小有序集合的大小,M 为输出有序集合的大小) |
ZSet(有序集合)是 Redis 中强大且灵活的数据类型,常用于需要元素排序和按分数检索的场景,如排行榜、带权重的任务队列等。通过合理选择 ZSet 命令,可以高效地处理这些应用场景。
三、ZSet 类型编码方式
Redis 中的 ZSet(有序集合)类型在内部使用两种主要的编码方式来存储数据,这两种编码方式分别是压缩列表(ziplist)和跳跃表(skiplist)。
3.1 压缩列表(ziplist)
压缩列表(ziplist)是一种紧凑的数据结构,通常用于存储元素较少、元素较小的有序集合。压缩列表以连续的内存块形式存储数据,每个节点可以包含一个或多个元素,而且它可以非常紧凑地存储整数和字符串等不同类型的元素。
压缩列表的特点包括:
- 紧凑性:压缩列表在内存中是紧凑的,适用于存储元素较少的有序集合。
- 快速访问:压缩列表支持通过索引快速访问元素,因为元素的位置是连续的。
- 节省内存:对于小型有序集合,压缩列表通常比跳跃表占用更少的内存。
3.2 跳跃表(skiplist)
跳跃表(skiplist)是一种基于链表的数据结构,通常用于存储元素较多、元素较大的有序集合。跳跃表使用多级索引来加速元素的查找操作,每级索引包含一部分元素,从而减少了查找元素的时间复杂度。
跳跃表的特点包括:
- 快速查找:跳跃表支持快速的元素查找,平均时间复杂度为 O(log N),其中 N 是有序集合的元素数量。
- 适用于大型数据集:对于包含大量元素的有序集合,跳跃表通常比压缩列表更有效,因为它不需要连续的内存块。
- 占用更多内存:跳跃表通常占用比较多的内存,因为它需要维护多级索引结构。
总之,Redis 根据有序集合的大小和元素的大小自动选择使用压缩列表或跳跃表来进行编码,以平衡内存使用和操作效率。选择编码方式时需要考虑数据的规模和操作的性能需求。
四、ZSet 使用场景
场景:排行榜系统
假设你正在开发一个社交平台,需要维护每天的用户赞数排行榜。以下是如何使用 Redis 的有序集合来实现这个场景:
-
添加用户赞数
当用户发布一篇文章并获得点赞时,使用
ZADD
命令将用户的点赞数添加到相应的排行榜中,同时使用ZINCRBY
命令来增加用户的点赞数。ZADD user:ranking:2022-03-15 3 james ZINCRBY user:ranking:2022-03-15 1 james
这些命令将用户 “james” 的点赞数添加到日期为 “2022-03-15” 的排行榜中,并在之后每次获得点赞时增加点赞数。
-
取消用户赞数
如果需要删除用户的点赞数,例如用户注销或发生违规行为,可以使用
ZREM
命令从排行榜中删除用户。ZREM user:ranking:2022-03-15 tom
这个命令将用户 “tom” 从排行榜中删除。
-
展示获取赞数最多的用户
要展示获取赞数最多的用户,可以使用
ZREVRANGE
命令,它返回指定排行榜的前 N 名用户。ZREVRANGE user:ranking:2022-03-15 0 9
这个命令将返回日期为 “2022-03-15” 的排行榜中前 10 名用户。
-
展示用户信息和分数
用户信息可以存储在哈希类型中,每个用户的信息使用用户名称作为键后缀。使用
HGETALL
命令可以获取用户的详细信息,使用ZSCORE
和ZRANK
命令可以获取用户的分数和排名。HGETALL user:info:james ZSCORE user:ranking:2022-03-15 mike ZRANK user:ranking:2022-03-15 mike
通过这些 Redis 操作,你可以实现一个完整的排行榜系统,用于跟踪用户的点赞数、取消点赞数、展示排行榜和获取用户信息。这对于社交平台、新闻网站等应用非常有帮助,可以提供实时的排名和用户信息。