首页 > 数据库 >Redis Set和Zset使用详解

Redis Set和Zset使用详解

来源:互联网 2026-07-10 08:42:07

Set 集合 集合类型同样是用来存储多个字符串元素的数据结构,但与列表类型不同——集合中的元素是无序的,且不允许重复。可以将其想象成一个装满各种颜色球的无序袋子,每种颜色在袋子中只能出现一个球。 一个集合最多可以存储 2^32-1 个元素,这一容量在绝大多数日常应用中已经足够使用。 Redis 的

Set 集合

集合类型同样是用来存储多个字符串元素的数据结构,但与列表类型不同——集合中的元素是无序的,且不允许重复。可以将其想象成一个装满各种颜色球的无序袋子,每种颜色在袋子中只能出现一个球。

一个集合最多可以存储 2^32-1 个元素,这一容量在绝大多数日常应用中已经足够使用。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

Redis 的 Set 不仅支持常规的增删改查操作,还提供了多个集合之间的交集、并集、差集运算。合理利用这一特性,可以在实际开发中解决许多棘手问题。

Redis Set和Zset使用详解

基础命令

SADD

向集合中添加一个或多个元素。如果添加的元素已经存在,集合会自动忽略该元素。

语法:

SADD key member [member ...]

返回值:本次实际成功添加的元素个数。

示例:

Redis Set和Zset使用详解

SMEMBERS

查看集合中所有元素。由于集合是无序的,返回的元素顺序不固定。

语法:

SMEMBERS key

返回值:所有元素的列表。

示例:

Redis Set和Zset使用详解

SISMEMBER

判断一个元素是否存在于集合中。

语法:

SISMEMBER key member

返回值:1 表示存在,0 表示不存在(或 key 本身不存在)。

示例:

Redis Set和Zset使用详解

SCARD

获取集合的大小,即集合中元素的个数。

语法:

SCARD key

返回值:集合内的元素个数。

示例:

Redis Set和Zset使用详解

SPOP

从集合中随机删除并返回一个或多个元素。由于集合无序,删除哪个元素是随机的。

语法:

SPOP key [count]

count 指定要删除的个数,不写默认删除 1 个。

返回值:被随机取出的元素。

示例:

Redis Set和Zset使用详解

SRANDMEMBER

与 SPOP 类似,但只随机查询元素,不进行删除。

语法:

srandmember key [count]

示例:

Redis Set和Zset使用详解

SMOVE

将一个元素从一个集合移动到另一个集合。

语法:

SMOVE source destination member

返回值:1 表示成功,0 表示失败(例如源集合中不存在该元素)。

示例:

Redis Set和Zset使用详解

SREM

从集合中删除指定的一个或多个元素。

语法:

SREM key member [member ...]

返回值:本次操作实际删除的元素个数。

示例:

Redis Set和Zset使用详解

集合间操作

真正让 Set 脱颖而出的,是它支持的三种基本集合运算:交集(inter)、并集(union)和差集(diff)。概念上并不复杂:

Redis Set和Zset使用详解

SINTER

获取多个集合的交集(即同时存在于这些集合中的元素)。

语法:

SINTER key [key ...]

返回值:交集元素列表。

示例:

Redis Set和Zset使用详解

SINTERSTORE

计算交集,并将结果保存到一个新的集合中。

语法:

SINTERSTORE destination key [key ...]

返回值:结果集合的元素个数。

示例:

Redis Set和Zset使用详解

SUNION

获取多个集合的并集(即出现在任意一个集合中的元素)。

语法:

SUNION key [key ...]

返回值:并集元素列表。

示例:

Redis Set和Zset使用详解 Redis Set和Zset使用详解

SUNIONSTORE

计算并集,并将结果保存到一个新的集合中。

语法:

SUNIONSTORE destination key [key ...]

返回值:结果集合的元素个数。

示例:

Redis Set和Zset使用详解

SDIFF

获取多个集合的差集(即只在第一个集合中存在,而不在其他集合中的元素)。

语法:

SDIFF key [key ...]

返回值:差集元素列表。

示例:

Redis Set和Zset使用详解

SDIFFSTORE

计算差集,并将结果保存到一个新的集合中。

语法:

SDIFFSTORE destination key [key ...]

返回值:结果集合的元素个数。

示例:

Redis Set和Zset使用详解 Redis Set和Zset使用详解

命令小结

Redis Set和Zset使用详解

内部编码

Redis 中的 Set 底层有两种存储方式,具体使用哪种由 Redis 自动选择:

  • intset(整数集合):如果集合中的所有元素都是整数,且元素数量少于配置项 set-max-intset-entries(默认 512 个),则 Redis 采用紧凑的整数存储方式,可节省大量内存。
  • hashtable(哈希表):当不满足 intset 条件时(例如元素不是整数,或元素数量过多),存储方式会退化为 hashtable。

使用场景

Set 最经典的应用场景是标签系统。例如,为用户打上“喜欢娱乐”、“喜欢体育”、“历史迷”等标签。通过这些标签,可以方便地找出具有共同爱好的人群,或计算某个用户的所有标签。在电商网站中,针对不同标签的用户进行商品推荐,转化效果往往能得到显著提升。

Zset 有序集合

相较于前几种数据类型,有序集合(Sorted Set)可能让新手感到有些陌生。它和 Set 一样,不允许出现重复成员,但每个成员都关联着一个分数——一个浮点数。正是这个分数,使得集合中的元素变得有序。这种有序并非基于下标,而是按照分数从低到高进行排序。

其大致结构如下,以三国武将的武力值排序为例:

Redis Set和Zset使用详解

除了常规操作,Zset 还支持按分数范围查找、计算成员排名等功能。合理运用这些特性,许多场景的处理会变得非常便捷。

重要提醒:Zset 中元素不能重复,但分数可以重复。好比一场考试,每个人只能有一个分数,但同分的情况很常见。

下面的表格有助于快速区分列表、集合和有序集合:

Redis Set和Zset使用详解

基础命令

ZADD

向有序集合中添加元素及其分数。分数必须是 double 类型,同时支持 +inf/-inf 表示正负无穷。

ZADD 附带了一些选项,虽然用得不多,但足够灵活:

  • XX:只更新已存在的元素。
  • NX:只添加新元素。
  • CH:默认返回新添加的元素个数;带上此选项后,更新的元素也会被计入。
  • INCR:类似于 ZINCRBY 的效果,为元素增加指定分数。
  • LT:更新已存在的元素,但仅当新分数低于当前分数时才执行更新。
  • GT:更新已存在的元素,但仅当新分数高于当前分数时才执行更新。

语法:

ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]

返回值:本次添加成功的元素个数。

示例:

Redis Set和Zset使用详解

当前查询结果是有序的(升序):

Redis Set和Zset使用详解

修改赵云的分数:

Redis Set和Zset使用详解

带上 nx 选项,仅在元素不存在时添加,返回值是新增元素的个数。

Redis Set和Zset使用详解

带上 xx 选项,仅当元素存在时才更新。由于没有新增元素,返回 0。

Redis Set和Zset使用详解

不加 ch 时,只返回新增元素个数;带上 ch 后,修改的元素也会被计入。

Redis Set和Zset使用详解

ZCARD

获取有序集合中的元素个数。

语法:

ZCARD key

返回值:有序集合内的元素个数。

示例:

Redis Set和Zset使用详解

ZCOUNT

统计分数在指定范围内的元素个数。默认包含边界,可以使用 ( 排除边界值。

语法:

ZCOUNT key min max

返回值:符合条件的元素个数。

示例:

Redis Set和Zset使用详解

默认包含边界:

Redis Set和Zset使用详解

如果不包含边界,需要加上 (

ZRANGE

按分数升序,返回指定下标范围内的元素。加上 WITHSCORES 可同时返回分数。

语法:

ZRANGE key start stop [WITHSCORES]

start 和 stop 为下标,从 0 开始,支持负数。

返回值:区间内的元素列表。

示例:

Redis Set和Zset使用详解

ZREVRANGE

与 ZRANGE 几乎相同,但分数按降序排列。需要注意的是,该命令可能在 6.2.0 版本后被废弃,并合并到 ZRANGE 中。

语法:

ZREVRANGE key start stop [WITHSCORES]

示例:

Redis Set和Zset使用详解

ZRANGEBYSCORE

按分数范围返回元素,默认包含边界。同样,该命令可能在 6.2.0 之后被废弃,并合并到 ZRANGE 中。

语法:

ZRANGEBYSCORE key min max [WITHSCORES]

示例:

Redis Set和Zset使用详解

ZPOPMAX

删除并返回分数最高的一个或多个元素。

语法:

ZPOPMAX key [count]

示例:

Redis Set和Zset使用详解

一个有趣的细节:如果分数最高的元素有多个,ZPOPMAX 仍然只会删除其中一个。

Redis Set和Zset使用详解

BZPOPMAX

ZPOPMAX 的阻塞版本。如果指定的 key 中没有元素,它会一直等待,直到有新的最大元素出现。

语法:

BZPOPMAX key [key ...] timeout

示例:

Redis Set和Zset使用详解

可以看到,刚开始 key 中没有数据,命令被阻塞,插入元素后立即返回。

ZPOPMIN

删除并返回分数最低的一个或多个元素。

语法:

ZPOPMIN key [count]

示例:

Redis Set和Zset使用详解

BZPOPMIN

ZPOPMIN 的阻塞版本。

语法:

BZPOPMIN key [key ...] timeout

ZRANK

返回指定元素按分数升序排列的排名(从 0 开始)。

语法:

ZRANK key member

示例:

Redis Set和Zset使用详解

ZREVRANK

返回指定元素按分数降序排列的排名。

语法:

ZREVRANK key member

ZSCORE

直接查询指定元素的分数。

语法:

ZSCORE key member

示例:

Redis Set和Zset使用详解

ZREM

删除指定的一个或多个元素。

语法:

ZREM key member [member ...]

示例:

Redis Set和Zset使用详解

ZREMRANGEBYRANK

按排名(升序)删除指定范围内的元素。范围是左闭右闭。

语法:

ZREMRANGEBYRANK key start stop

示例:

Redis Set和Zset使用详解

ZREMRANGEBYSCORE

按分数范围删除元素,默认包含边界,可使用 ( 排除边界值。

语法:

ZREMRANGEBYSCORE key min max

示例:

Redis Set和Zset使用详解

ZINCRBY

为指定元素的分数增加一个值。

语法:

ZINCRBY key increment member

返回值:增加后的新分数。

示例:

Redis Set和Zset使用详解

集合间操作

Zset 也支持交集和并集操作,但比 Set 更复杂——因为涉及分数的合并和重新计算。

有序集合的交集操作:

Redis Set和Zset使用详解

ZINTERSTORE

计算多个有序集合的交集,并将结果保存到目标有序集合中。合并时,每个元素会按照指定的聚合方式(SUM/MIN/MAX)和权重(WEIGHTS)生成新的分数。

语法:

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE ]

返回值:结果集合中的元素个数。

示例 1:

Redis Set和Zset使用详解 Redis Set和Zset使用详解

示例 2:

Redis Set和Zset使用详解 Redis Set和Zset使用详解

这里 weights 2 3 表示:第一个集合的分数都乘以 2(10,20,30 → 20,40,60),第二个集合的分数都乘以 3(15,25,35 → 45,75,105)。最终交集得到的 zhangshan 分数为 20+45=65。

示例 3:

Redis Set和Zset使用详解

通过 AGGREGATE 可以指定分数合并的方式,默认是 SUM,也可以选择 MIN 或 MAX。

有序集合的并集操作:

Redis Set和Zset使用详解

ZUNIONSTORE

计算多个有序集合的并集,并将结果保存到目标有序集合中。与交集类似,只是运算改为并集。

语法:

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE ]

示例 1:

Redis Set和Zset使用详解

示例 2:

Redis Set和Zset使用详解

命令小结

Redis Set和Zset使用详解

内部编码

有序集合的底层也有两种编码方式:

  • ziplist(压缩列表):当元素个数少于配置项 zset-max-ziplist-entries(默认 128 个),且每个元素的值小于 zset-max-ziplist-value(默认 64 字节)时,会使用 ziplist 以节省内存。
  • skiplist(跳表):当不满足 ziplist 条件时,存储方式会切换为 skiplist。它具有较高的查询效率,是应对大数据量的主流方案。

使用场景

Zset 最经典的使用场景是各种排行榜。例如,网站的实时热门内容可以按照阅读量、点赞量或时间进行排序,使用 Zset 实现起来非常便捷。

渐进式遍历

使用过 KEYS 命令的用户可能都吃过它的亏——数据量大时,会阻塞整个 Redis 实例。为解决这一问题,Redis 提供了 SCAN 命令,它可以将一次大操作拆分为多次小操作,每次只返回一小部分数据。每次 SCAN 的时间复杂度为 O(1),但要遍历完所有数据,需要多次执行。

大致过程如下:

Redis Set和Zset使用详解
  • 第一次 scan 从 0 开始。
  • 当 scan 返回的下次位置为 0 时,表示遍历结束。

SCAN

语法:

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]

其中 COUNT 后面接数字,表示建议每次返回多少条。需要注意的是,这只是建议,实际返回的条数可能与之不同。

返回值:下一次 scan 的游标(cursor)以及本次获取到的键。

示例:

Redis Set和Zset使用详解 Redis Set和Zset使用详解

第一次遍历,返回了游标 15,因此下次应从 15 开始。第二次返回的游标是 0,遍历结束。

示例 2:

Redis Set和Zset使用详解

当设置 COUNT 3 时,实际返回了 4 条,再次说明 count 只是一个建议。

除了 SCAN,Redis 还针对哈希、集合、有序集合分别提供了 HSCANSSCANZSCAN 命令,用法大同小异。

需要特别留意的是:渐进式遍历解决了阻塞问题,但由于在遍历过程中键可能被增、删、改,因此有可能出现重复遍历或遗漏的情况。这在生产环境中需要仔细考量。

数据库管理

Redis 提供了几个数据库级别的管理命令:dbsizeselectflushdbflushall

切换数据库

select dbIndex

与 MySQL 这类关系型数据库不同,Redis 使用数字来标识不同的数据库。默认配置下,Redis 有 16 个数据库,编号从 0 到 15。执行 select 0 会切换到第一个数据库,select 15 则是最后一个。不同数据库之间互不干扰。

Redis Set和Zset使用详解

不过,经过多年的实践,目前并不建议在项目中使用多数据库功能。如果需要完全隔离的两套数据,更好的做法是启动多个 Redis 实例,而不是在同一个实例中切换数据库。原因很简单:Redis 本身对多数据库的支持有限,底层依然是单线程模型,切换数据库仍需排队。此外,多数据库会使开发调试和运维变得复杂。因此,通常的做法是始终使用第 0 号数据库,其他号码可以忽略。

示例:

Redis Set和Zset使用详解

清除数据库

flushdb 只清除当前数据库,flushall 清除所有数据库的数据。

无论多么自信,永远不要在生产环境执行这两条命令,除非你确实想体验“从删库到跑路”的感觉。

总结

Set 和 Zset 是 Redis 数据类型中比较有针对性的两个工具。Set 擅长集合运算和标签系统,Zset 则天生为排行榜设计。理解它们的底层编码和适用场景,在日常开发中能少走不少弯路。当然,再强大的工具也经不住滥用,例如多数据库部分,能避免应尽量避免。

以上技术要点基本覆盖了 Set 和 Zset 的核心内容。如果觉得有用,希望这篇文章能帮助你对 Redis 的这两个类型建立起更扎实的认知。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。