Redis命令-Set命令

一、前言:Set 不是"集合",而是高效工具箱

Redis 的 Set(集合) 是一个无序、唯一、基于哈希表 的数据结构,天然支持去重集合运算

典型应用场景包括:

  • 用户标签系统(如"科技"、"金融")
  • 社交关系(好友、关注、粉丝)
  • 抽奖去重(已中奖用户不再参与)
  • 共同兴趣推荐(交集计算)

本文将系统讲解 Redis Set 的核心命令 ,并通过真实业务案例展示其强大能力。


二、Set 核心命令速查表

命令 作用 时间复杂度
SADD key member [member ...] 添加一个或多个成员 O(1) 每个成员
SREM key member [member ...] 移除一个或多个成员 O(1) 每个成员
SMEMBERS key 获取所有成员 O(N),N=成员数
SCARD key 获取集合大小 O(1)
SISMEMBER key member 判断成员是否存在 O(1)
SRANDMEMBER key [count] 随机返回一个或多个成员 O(N),N=count
SPOP key [count] 随机弹出并移除成员 O(N)
SMOVE source destination member 将成员从一个集合移到另一个 O(1)

集合运算命令

命令 作用 时间复杂度
SINTER key [key ...] 求多个集合的交集 O(N×M),N=最小集合大小,M=集合数
SUNION key [key ...] 求多个集合的并集 O(N+M+...)
SDIFF key [key ...] 求第一个集合与其他集合的差集 O(N+M+...)
SINTERSTORE dest key [key ...] 将交集结果存储到新集合 同 SINTER
SUNIONSTORE dest key [key ...] 将并集结果存储 同 SUNION
SDIFFSTORE dest key [key ...] 将差集结果存储 同 SDIFF

💡 关键特性

  • 成员唯一(自动去重)
  • 无序(不保证插入顺序)
  • 支持高效集合运算

三、常用命令详解与示例

3.1 基础操作:添加、查询、删除

bash 复制代码
# 添加标签(自动去重)
127.0.0.1:6379> SADD user:1001:tags "tech" "finance" "ai"
(integer) 3

# 再次添加重复标签
127.0.0.1:6379> SADD user:1001:tags "tech" "blockchain"
(integer) 1  # 只新增了 "blockchain"

# 查询所有标签
127.0.0.1:6379> SMEMBERS user:1001:tags
1) "ai"
2) "blockchain"
3) "finance"
4) "tech"

# 判断是否包含某标签
127.0.0.1:6379> SISMEMBER user:1001:tags "ai"
(integer) 1

# 获取标签数量
127.0.0.1:6379> SCARD user:1001:tags
(integer) 4

3.2 随机操作:SRANDMEMBER / SPOP

bash 复制代码
# 随机抽取 2 个标签(不移除)
127.0.0.1:6379> SRANDMEMBER user:1001:tags 2
1) "finance"
2) "tech"

# 随机弹出 1 个标签(移除)
127.0.0.1:6379> SPOP user:1001:tags
"ai"

典型场景:抽奖、随机推荐、A/B 测试分组


3.3 集合运算:交集、并集、差集

bash 复制代码
# 用户 A 的兴趣
SADD user:A:interests "music" "movie" "game"
# 用户 B 的兴趣
SADD user:B:interests "movie" "sports" "game"

# 共同兴趣(交集)
127.0.0.1:6379> SINTER user:A:interests user:B:interests
1) "game"
2) "movie"

# 所有兴趣(并集)
127.0.0.1:6379> SUNION user:A:interests user:B:interests
1) "game"
2) "movie"
3) "music"
4) "sports"

# A 有但 B 没有的兴趣(差集)
127.0.0.1:6379> SDIFF user:A:interests user:B:interests
1) "music"

🔥 这是实现"可能认识的人"、"猜你喜欢"的核心逻辑!


四、Set 的内部编码优化

Redis 对小 Set 使用 intset(整数集合)hashtable(哈希表) 编码:

复制代码
# redis.conf 默认配置
set-max-intset-entries 512   # 成员全为整数且 ≤512 时用 intset
  • intset:内存更省,仅支持整数
  • hashtable:通用,支持字符串

💡 建议

  • 小集合(如标签、好友)性能极佳
  • 避免存储超大 Set(如 > 100 万元素)

五、实战应用场景

场景 1:用户标签系统

java 复制代码
// Java (Lettuce)
String userId = "1001";
String tagKey = "user:" + userId + ":tags";

// 添加标签
redis.sadd(tagKey, "tech", "ai");

// 判断用户是否属于"科技"人群
Boolean isTechUser = redis.sismember(tagKey, "tech");

// 获取所有带"ai"标签的用户(需反向索引,见下文)

📌 扩展 :如需"反查",可建立 tag → users 的反向 Set:

bash 复制代码
SADD tag:ai user:1001 user:1002

场景 2:社交关系(好友/关注)

python 复制代码
# Python (redis-py)
# 用户 1001 关注了 2001, 2002
r.sadd("follow:1001", "2001", "2002")

# 用户 2001 的粉丝
r.sadd("fans:2001", "1001")

# 判断是否关注
r.sismember("follow:1001", "2001")  # True

# 共同关注(我关注的人中,也关注了 X 的人)
r.sinter("follow:1001", "fans:2002")

优势:O(1) 判断关系,O(N) 计算交集


场景 3:抽奖去重

bash 复制代码
# 已中奖用户
SADD lottery:winners user:1001 user:1002

# 新用户参与抽奖前检查
SISMEMBER lottery:winners user:1003  # 返回 0 → 可参与

# 中奖后加入
SADD lottery:winners user:1003

六、常见误区与最佳实践

❌ 误区 1:用 SMEMBERS 遍历大集合

  • 问题:阻塞主线程,网络爆炸
  • 建议 :使用 SSCAN 游标分批遍历(适用于 > 1000 元素)
bash 复制代码
127.0.0.1:6379> SSCAN big_set 0 COUNT 100

❌ 误区 2:频繁执行多 Key 集合运算

  • 问题SINTER key1 key2 key3 若 key 很大,会阻塞
  • 建议
    • 限制参与运算的集合大小
    • 使用 SINTERSTORE 异步生成结果集

✅ 最佳实践

  1. 命名规范 :如 tag:aifollow:user_id
  2. 设置 TTL:临时集合(如抽奖)加过期时间
  3. 监控大小 :通过 SCARD + 告警防止膨胀
  4. 避免大 Value:成员建议 < 64 字节

七、Set vs List vs Sorted Set 选型建议

需求 推荐类型
去重 + 无序 Set
有序列表 + 范围查询 Sorted Set
队列/栈/时间线 List
对象属性存储 Hash

📌 Set 的核心价值:唯一性 + 集合运算


八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
天涯明月19932 小时前
服务网格完全指南:从基础概念到生产实践
java·服务器·数据库·分布式·微服务
Han.miracle2 小时前
万字详解 Lombok 构造方法注解:@AllArgsConstructor 非空校验实现与最佳实践
java·前端·数据库
catchadmin2 小时前
Chrome DevTools MCP 让 AI 无缝接管浏览器调试会话
前端·chrome·chrome devtools
吠品2 小时前
SQL Server 2012日志文件管理:解决过大问题的全面指南
服务器·数据库·oracle
熙胤2 小时前
【MySQL】数据库和表的操作
数据库·mysql·oracle
掘根2 小时前
【即时通讯系统】环境搭建7——ODB
数据库·oracle
要开心吖ZSH2 小时前
关于Redis的持久化方式(RDB、AOF)
数据库·redis·缓存
umeelove352 小时前
使用 Qt 插件和 SQLCipher 实现 SQLite 数据库加密与解密
数据库·qt·sqlite
不爱学英文的码字机器2 小时前
毫秒级破局:金仓数据库“连接条件下推”破解SQL性能困局
数据库·oracle