redis---set详解

在 Redis 中,Set(集合)是一种无序、唯一的字符串元素集合,支持高效的成员添加、删除、查询以及集合间的交集、并集、差集等操作,适用于存储不重复的数据并进行关联分析(如共同好友、标签聚合等)。

一、核心特性

  1. 无序性:集合中的元素没有固定顺序,不能通过索引访问。
  2. 唯一性:每个元素在集合中仅出现一次,重复添加会被自动忽略。
  3. 高效操作 :添加、删除、判断元素是否存在的时间复杂度均为 O(1),集合间运算(交集、并集等)效率也极高。
  4. 内部编码 :根据元素数量自动选择编码:
    • intset(整数集合):当集合元素全为整数且数量较少(默认 < 512 个)时使用,节省内存。
    • hashtable(哈希表):元素包含字符串或数量较多时使用,支持更灵活的存储。

二、常用命令

1. 基础操作

命令格式 说明 示例 返回值
SADD key member [member...] 向集合添加一个或多个元素 SADD tags "java" "python" 成功添加的元素数量
SREM key member [member...] 从集合删除一个或多个元素 SREM tags "java" 成功删除的元素数量
SMEMBERS key 返回集合中所有元素(无序) SMEMBERS tags 元素列表(无固定顺序)
SISMEMBER key member 判断元素是否在集合中 SISMEMBER tags "python" 1(存在)或 0(不存在)
SCARD key 返回集合中元素的数量 SCARD tags 元素总数
SRANDMEMBER key [count] 随机返回集合中 count 个元素(不删除) SRANDMEMBER tags 2 随机元素列表(默认返回 1 个)
SPOP key [count] 随机删除并返回集合中 count 个元素 SPOP tags 1 被删除的元素(默认删除 1 个)

2. 集合间运算

命令格式 说明 示例 返回值
SINTER key1 [key2...] 计算多个集合的交集(共同元素) SINTER set1 set2 交集元素列表
SINTERSTORE dest key1 [key2...] 将交集结果存储到 dest 集合 SINTERSTORE common set1 set2 交集元素数量
SUNION key1 [key2...] 计算多个集合的并集(所有元素) SUNION set1 set2 并集元素列表
SUNIONSTORE dest key1 [key2...] 将并集结果存储到 dest 集合 SUNIONSTORE all set1 set2 并集元素数量
SDIFF key1 [key2...] 计算多个集合的差集(key1 独有的元素) SDIFF set1 set2 差集元素列表
SDIFFSTORE dest key1 [key2...] 将差集结果存储到 dest 集合 SDIFFSTORE unique set1 set2 差集元素数量

3. 其他实用命令

命令格式 说明 示例
SMOVE source dest member 将元素从 source 集合移动到 dest 集合 SMOVE set1 set2 "java"
S清 key 清空集合(Redis 无直接命令,需用 DEL key 删除集合后重建) DEL tags

三、使用示例

场景:存储用户标签并分析

  1. 给用户添加标签:

    redis

    复制代码
    SADD user:100:tags "java" "backend" "linux"
    SADD user:101:tags "python" "backend" "docker"
  2. 查看用户 100 的所有标签:

    redis

    复制代码
    SMEMBERS user:100:tags
    # 输出:1) "java" 2) "backend" 3) "linux"(顺序不固定)
  3. 计算两个用户的共同标签(交集):

    redis

    复制代码
    SINTER user:100:tags user:101:tags
    # 输出:1) "backend"
  4. 计算用户 100 独有的标签(差集):

    redis

    复制代码
    SDIFF user:100:tags user:101:tags
    # 输出:1) "java" 2) "linux"

四、应用场景

  1. 去重存储:如存储用户浏览过的商品 ID(避免重复)。
  2. 关联分析:如计算共同好友、相似兴趣标签(基于交集)。
  3. 随机推荐 :用 SRANDMEMBER 随机返回集合元素(如随机推荐文章、商品)。
  4. 标签系统:为用户或内容添加多标签,通过集合运算快速筛选(如 "同时包含标签 A 和 B 的内容")。
  5. 黑名单 / 白名单 :用 SISMEMBER 快速判断用户是否在黑名单中。

五、注意事项

  1. 无序性SMEMBERS 返回的元素顺序不固定,若需有序集合,应使用 Sorted Set(ZSet)。
  2. 元素类型:集合元素只能是字符串(或整数,Redis 会自动转换为字符串存储)。
  3. 内存占用intset 编码比 hashtable 更节省内存,尽量存储整数类型元素(如 ID)以优化内存。
  4. 大数据量集合运算 :对超大型集合进行交集 / 并集运算可能耗时,建议使用 SINTERSTORE 等命令将结果存储后再处理,避免重复计算。

六、内部编码

Redis 中的 SET 类型(集合)会根据存储元素的特点自动选择不同的内部编码方式,以优化内存占用和操作性能。主要有以下两种内部编码:

1. intset(整数集合)

当集合满足以下两个条件时,Redis 会使用 intset 编码:

• 集合中的所有元素都是整数(64 位有符号整数)

• 集合元素数量不超过配置参数 set-max-intset-entries 的值(默认值为 512)

特点:

• 内存紧凑,以数组形式存储整数,按升序排列

• 支持快速的查找、插入、删除操作(时间复杂度 O (log n))

• 不存储重复元素,自动去重

示例:

复制代码
SADD numbers 1 3 5 7 9  # 会使用 intset 编码

2. hashtable(哈希表)

当集合不满足 intset 的条件时(如包含字符串元素,或元素数量超过阈值),Redis 会使用 hashtable 编码。

这里的 hashtable 与 Redis 的 HASH 类型底层结构类似,是一种字典结构:

  • 键:集合中的元素值
  • 值:统一为 NULL(仅用键来存储集合元素,值无实际意义)

特点

  • 支持存储任何类型的元素(字符串、整数等)
  • 元素数量无严格限制(仅受内存限制)
  • 查找、插入、删除操作的平均时间复杂度为 O (1)

示例

复制代码
SADD fruits "apple" "banana" "cherry"  # 包含字符串,使用 hashtable 编码
SADD large-set 1 2 3 ... 513           # 元素数量超过 512,使用 hashtable 编码

编码转换规则

  • intset 中的元素数量超过 set-max-intset-entries 时,会自动转换为 hashtable
  • intset 中插入非整数元素时,会立即转换为 hashtable
  • 转换是单向的:intsethashtable(一旦转换为 hashtable,不会再转回 intset
相关推荐
ningqw36 分钟前
Redis-分布式缓存
redis
一叶飘零_sweeeet44 分钟前
如何避免MyBatis二级缓存中的脏读
java·redis·mybatis
3Cloudream2 小时前
互联网大厂Java面试深度解析:从基础到微服务云原生的全场景模拟
java·spring boot·redis·elasticsearch·微服务·kafka·电商架构
郭俊强5 小时前
nestjs 连接redis
数据库·redis·缓存
lssjzmn6 小时前
针对不同使用场景,Redis的Value应该如何序列化,优缺点如何,进来看
spring boot·redis
工业甲酰苯胺7 小时前
Redis支持事务吗?了解Redis的持久化机制吗?
数据库·redis·bootstrap
万行11 小时前
点评项目(Redis中间件)&第一部分Redis基础
java·数据库·redis·缓存·中间件
Seven9712 小时前
一文带你了解缓存和数据库一致性问题
redis·mysql
喪彪1 天前
Ubuntu操作系统下使用mysql、mongodb、redis
redis·mysql·mongodb